Malloc 总是 returns 一个 NULL 指针; Visual Studio 2022
Malloc always returns a NULL pointer; Visual Studio 2022
这可能是一个重复的问题,但我检查了其他类似的问题,但从未真正找到我要找的东西(或者我相信)。
考虑以下代码:
#include <iostream>
#include <stdlib.h>
int main()
{
char* s = (char*)malloc(2 * sizeof(char));
*s = 'M';
s++;
*s = 'I';
std::cout << s[-1] << s[0] << s[1];
}
输出:
MI²
我的问题是,每当我尝试使用 malloc
/calloc
/realloc
时,我总是会弹出相同的错误消息,提示 s(参见上面的代码) 是一个 'unreferenced NULL-pointer'.
我真的看不出这里有什么问题。特别是因为 'M' 和 'I' 都已分配给我通过 malloc 初始化的数组,但它们位于奇怪的位置。我期望:s[0] = 'M
' 和 s[1] = 'I'
但实际上是 s[-1] = 'M'
和 s[0] = 'I'
,我觉得这很奇怪。
我哪里错了?
你不应该在行 s++;
中更改 s
s
指向您分配的基础。所以当你增加它时,s[0] 指向 'I'.
是很自然的
如果您想分配内存分配的第二个位置,或者就此而言的第 i 个位置,您可以使用此 s[i] = 'M';
,或者您可以这样做:*(s+i) = 'M';
。\
但前者是更好的做法,因为它更具可读性。我相信大多数人在面对后者时都会停下来,因为现在已经很少见了。
附加信息
事实上,当你使用s[i] = 'M';
时,编译器只是将它翻译成*(s+i) = 'M';
。所以这个 []
只是一个在指针类型上定义的运算符,它只是将其参数(在大多数情况下名为 i
)添加到指针的基址。
需要说明的是,该消息是编译器发出的警告,并不是您从 malloc 中获取 null,它警告您可能并没有检查
https://docs.microsoft.com/en-us/cpp/code-quality/c6011?view=msvc-170
如果您这样做,消息就会消失
char* s = (char*)malloc(2 * sizeof(char));
if (s != NULL)
{
*s = 'M';
s++;
*s = 'I';
std::cout << s[-1] << s[0] << s[1];
}
虽然还有另一个警告
https://docs.microsoft.com/en-us/cpp/code-quality/c6200?view=msvc-170
这是警告 s[-1]
看起来很奇怪。它忽略了你之前做过 s++ 的事实,这使得这没问题。
不好的是
std::cout << s[-1] << s[0] << s[1];
------------------------------*****
这是在分配结束后访问数据,结果是未定义的行为。
如果你这样做
int main()
{
char* s = (char*)malloc(2 * sizeof(char));
if (s != NULL)
{
s[0] = 'M';
s[1] = 'I';
std::cout << s[0] << s[1] << s[2];
}
}
这是做同样事情的更直接的方法,然后 VS 会警告你 s[2] 越界
这可能是一个重复的问题,但我检查了其他类似的问题,但从未真正找到我要找的东西(或者我相信)。
考虑以下代码:
#include <iostream>
#include <stdlib.h>
int main()
{
char* s = (char*)malloc(2 * sizeof(char));
*s = 'M';
s++;
*s = 'I';
std::cout << s[-1] << s[0] << s[1];
}
输出:
MI²
我的问题是,每当我尝试使用 malloc
/calloc
/realloc
时,我总是会弹出相同的错误消息,提示 s(参见上面的代码) 是一个 'unreferenced NULL-pointer'.
我真的看不出这里有什么问题。特别是因为 'M' 和 'I' 都已分配给我通过 malloc 初始化的数组,但它们位于奇怪的位置。我期望:s[0] = 'M
' 和 s[1] = 'I'
但实际上是 s[-1] = 'M'
和 s[0] = 'I'
,我觉得这很奇怪。
我哪里错了?
你不应该在行 s++;
中更改 s
s
指向您分配的基础。所以当你增加它时,s[0] 指向 'I'.
如果您想分配内存分配的第二个位置,或者就此而言的第 i 个位置,您可以使用此 s[i] = 'M';
,或者您可以这样做:*(s+i) = 'M';
。\
但前者是更好的做法,因为它更具可读性。我相信大多数人在面对后者时都会停下来,因为现在已经很少见了。
附加信息
事实上,当你使用s[i] = 'M';
时,编译器只是将它翻译成*(s+i) = 'M';
。所以这个 []
只是一个在指针类型上定义的运算符,它只是将其参数(在大多数情况下名为 i
)添加到指针的基址。
需要说明的是,该消息是编译器发出的警告,并不是您从 malloc 中获取 null,它警告您可能并没有检查
https://docs.microsoft.com/en-us/cpp/code-quality/c6011?view=msvc-170
如果您这样做,消息就会消失
char* s = (char*)malloc(2 * sizeof(char));
if (s != NULL)
{
*s = 'M';
s++;
*s = 'I';
std::cout << s[-1] << s[0] << s[1];
}
虽然还有另一个警告
https://docs.microsoft.com/en-us/cpp/code-quality/c6200?view=msvc-170
这是警告 s[-1]
看起来很奇怪。它忽略了你之前做过 s++ 的事实,这使得这没问题。
不好的是
std::cout << s[-1] << s[0] << s[1];
------------------------------*****
这是在分配结束后访问数据,结果是未定义的行为。
如果你这样做
int main()
{
char* s = (char*)malloc(2 * sizeof(char));
if (s != NULL)
{
s[0] = 'M';
s[1] = 'I';
std::cout << s[0] << s[1] << s[2];
}
}
这是做同样事情的更直接的方法,然后 VS 会警告你 s[2] 越界