答案 0 :(得分:115)
根据规范,malloc(0)将返回“空指针或可以成功传递给free()的唯一指针”。
这基本上可以让你什么都不分配,但仍然可以将“artist”变量传递给free(),而不用担心。出于实际目的,它几乎与做:
artist = NULL;
答案 1 :(得分:46)
C标准(C17 7.22.3 / 1)说:
如果请求的空间大小为零,则行为是实现定义的: 返回空指针,或者行为就像大小一样 非零值,但返回的指针不得用于访问对象。
因此,malloc(0)
可以返回NULL
或可能无法解除引用的有效指针 。在任何一种情况下,在其上调用free()
都是完全有效的。
我并不认为malloc(0)
有多大用处,例如在循环中调用malloc(n)
的情况除外,n
可能为零。
查看链接中的代码,我认为作者有两个误解:
malloc(0)
返回有效指针始终和free(0)
不好。因此,他确保artist
和其他变量始终具有一些“有效”值。评论说:// these must always point at malloc'd data
。
答案 2 :(得分:10)
malloc(0)行为是特定于实现的。该库可以返回NULL或具有常规malloc行为,没有分配内存。无论它做什么,都必须在某处记录。
通常,它返回一个有效且唯一的指针,但不应该取消引用。另请注意,即使它实际上没有分配任何内容,它也会消耗内存。
可以重新分配非null malloc(0)指针。
尽管使用malloc(0)逐字逐句。它主要用于动态分配为零字节且您不关心验证它时。
答案 3 :(得分:5)
本页的其他地方有一个答案,“malloc(0)将返回一个有效的内存地址,其范围将取决于正在分配内存的指针类型”。这个陈述不正确(我没有足够的声誉来直接评论这个答案,所以不能直接把这个评论放在那里)。
执行malloc(0)将不自动分配正确大小的内存。 malloc函数不知道你将其结果投射到了什么。 malloc函数完全依赖于您提供的大小编号作为参数。你需要做malloc(sizeof(int))来获得足够的存储来保存int,例如,不是0。
答案 4 :(得分:3)
malloc(0)
对我没有任何意义。如果代码是可移植的,那么它必须考虑到malloc(0)
的NULL返回不是失败的事实。那么为什么不将NULL分配给artist
,因为这是一个有效的成功结果,并且代码更少,并且不会让维护程序员花时间搞清楚它?
malloc(SOME_CONSTANT_THAT_MIGHT_BE_ZERO)
或malloc(some_variable_which_might_be_zero)
可能也有它们的用途,尽管如果值为0,你还是要特别注意不要将NULL返回视为失败,但是0的大小应该是没关系。
答案 5 :(得分:3)
这里有很多半真正的答案,所以这里有很多事实。 malloc()
的手册页说:
如果size为0,则malloc()返回NULL或稍后可以的唯一指针值 成功传递给free()。
这意味着,绝对不能保证malloc(0)
的结果是唯一的或不是NULL。唯一的保证是由free()
的定义提供的,同样,这是man-page所说的内容:
如果ptr为NULL,则不执行任何操作。
因此,无论malloc(0)
返回什么,都可以安全地传递给free()
。但NULL
指针也是如此。
因此,撰写 artist = malloc(0);
绝不比写作 artist = NULL;
答案 6 :(得分:2)
不可否认,我以前从未见过这个,这是我第一次看到这种语法,可以说是一个功能矫枉过正的经典案例。结合里德的回答,我想指出有一个类似的东西,看起来像一个重载函数realloc
:
realloc(foo, size);
。当你传入一个非NULL指针并且大小为零来重新分配时,realloc的行为就好像你已经调用了free(...)realloc(foo, size);
。传入NULL指针并且大小不为零时,realloc的行为就像调用malloc(...)希望这有帮助, 最好的祝福, 汤姆。
答案 7 :(得分:2)
为什么你不应该这样做......
由于malloc的返回值是依赖于实现的,因此可能会返回NULL指针或其他一些地址。如果错误处理代码不检查大小和返回值,导致稳定性问题(崩溃)或甚至更严重的安全问题,这最终可能会导致堆缓冲区溢出。
考虑这个例子,如果大小为零,进一步通过返回的地址访问内存将损坏堆,并且实现返回非NULL值。
size_t size;
/* Initialize size, possibly by user-controlled input */
int *list = (int *)malloc(size);
if (list == NULL) {
/* Handle allocation error */
}
else {
/* Continue processing list */
}
请参阅CERT编码标准中的this Secure Coding page,我将上面的示例用于进一步阅读。
答案 8 :(得分:1)
要真正回答所提出的问题:没有理由这样做
答案 9 :(得分:0)
malloc(0)将返回NULL或一个可以正确传递给free的有效指针。虽然看起来它所指的内存是无用的,或者它无法写入或读取,但并非总是如此。 :)
int *i = malloc(0);
*i = 100;
printf("%d", *i);
我们期待这里出现分段错误,但令人惊讶的是,这会打印100个!这是因为当我们第一次调用malloc时,malloc实际上要求大量的内存。之后每次调用malloc都会使用来自那个大块的内存。只有在那个巨大的块结束后,才会要求新的记忆。
使用malloc(0):如果您希望后续malloc调用更快,则调用malloc(0)应该为您执行(边缘情况除外)。
答案 10 :(得分:0)
它实际上非常有用,并且(显然是恕我直言),返回NULL指针的允许行为已被破坏。动态指针不仅对它指向的内容有用,而且其地址是唯一的。返回NULL将删除该第二个属性。我编写的所有嵌入式malloc(实际上很多时候)都具有这种行为。
答案 11 :(得分:0)
在Windows中:
void *p = malloc(0);
将在本地堆上分配零长度缓冲区。返回的指针是一个有效的堆指针。malloc
最终使用默认的C运行时堆调用HeapAlloc
,然后调用RtlAllocateHeap
等。free(p);
使用HeapFree
释放堆上的0长度缓冲区。不释放它会导致内存泄漏。答案 12 :(得分:-1)
不确定,根据我发现的一些random malloc source代码,输入为0会导致返回值为NULL。因此,将Artist指针设置为NULL是一种疯狂的方法。
http://www.raspberryginger.com/jbailey/minix/html/lib_2ansi_2malloc_8c-source.html
答案 13 :(得分:-2)
这是使用valgrind内存检查工具运行后的分析。
anything with the R8..R15 regs and parts thereof
anything that accesses the new 8 bit regs: DIL, SIL, BPL, SPL
anything that accesses 64 bit registers.
这是我的示例代码:
==16740== Command: ./malloc0
==16740==
p1 = 0x5204040
==16740==
==16740== HEAP SUMMARY:
==16740== in use at exit: 0 bytes in 0 blocks
==16740== total heap usage: 2 allocs, 2 frees, 1,024 bytes allocated
==16740==
==16740== All heap blocks were freed -- no leaks are possible
默认情况下,分配1024个字节。如果我增加malloc的大小,分配的字节将增加1025,依此类推。
答案 14 :(得分:-3)
根据Reed Copsey回答和malloc的手册页,我写了一些例子来测试。我发现malloc(0)总是给它一个独特的价值。 看我的例子:
char *ptr;
if( (ptr = (char *) malloc(0)) == NULL )
puts("Got a null pointer");
else
puts("Got a valid pointer");
输出将是"有一个有效的指针",这意味着ptr
不为空。
答案 15 :(得分:-6)
只是为了纠正错误的印象:
artist = (char *) malloc(0);
永远不会返回NULL
;它与artist = NULL;
不一样。编写一个简单的程序,并将artist
与NULL
进行比较。 if (artist == NULL)
为false,if (artist)
为真。
答案 16 :(得分:-6)
malloc(0)
将返回一个有效的内存地址,其范围将取决于正在分配内存的指针类型。您也可以为存储区分配值,但这应该在使用指针类型的范围内。您还可以释放分配的内存。我将用一个例子解释这个:
int *p=NULL;
p=(int *)malloc(0);
free(p);
上面的代码可以在Linux机器上的gcc
编译器中正常工作。如果你有一个32位编译器,那么你可以提供整数范围内的值,即-2147483648到2147483647.同样适用于字符。请注意,如果声明的指针类型被更改,那么无论malloc
类型转换,值的范围都会发生变化,即
unsigned char *p=NULL;
p =(char *)malloc(0);
free(p);
p
将取0到255的char值,因为它被声明为unsigned int。