【发布时间】:2011-01-02 14:25:16
【问题描述】:
【问题讨论】:
【问题讨论】:
根据规范,malloc(0) 将返回“可以成功传递给 free() 的空指针或唯一指针”。
这基本上让您什么都不分配,但仍然可以将“艺术家”变量传递给对 free() 的调用,而无需担心。出于实际目的,它与做的几乎相同:
artist = NULL;
【讨论】:
realloc() 允许您传递malloc() 返回的任何有效指针。应该够了。
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。
【讨论】:
malloc(0)返回了一个有效的指针,那么malloc()返回NULL总是意味着“失败”,0不再是特例,更加一致。
malloc获取内存失败的情况是实现定义的,实现可以简单地定义size-0分配总是不可满足的(ENOMEM),现在malloc(0)返回0 (与errno==ENOMEM)是一致的。 :-)
realloc 一个malloc(0) 返回的指针吗?可以realloc((char*)NULL)吗?
malloc(0) 行为是特定于实现的。该库可以返回 NULL 或具有常规 malloc 行为,而无需分配内存。无论它做什么,都必须记录在某个地方。
通常,它返回一个有效且唯一的指针,但不应取消引用。另请注意,即使它实际上没有分配任何东西,它也会消耗内存。
可以重新分配非空 malloc(0) 指针。
尽管逐字逐句地使用 malloc(0) 并没有多大用处。它主要用于动态分配为零字节并且您不关心对其进行验证的情况。
【讨论】:
malloc() 必须在某处保留“内务管理信息”(例如,分配的块的大小和其他辅助数据)。所以,如果malloc(0)不返回NULL,它会使用内存来存储那个信息,如果不是free()d,就会构成内存泄漏。
malloc() 不会返回,或者返回NULL。
malloc(0) 返回一个唯一指针。然而,在标准 C 库的相同实现中,realloc(ptr, 0) 释放 ptr 并返回 NULL。
在此页面的其他地方有一个答案,开头是“malloc(0) 将返回一个有效的内存地址,其范围将取决于分配内存的指针类型”。这个说法是不正确的(我没有足够的声望直接评论那个答案,所以不能把这个评论直接放在下面)。
执行 malloc(0) 将不会自动分配正确大小的内存。 malloc 函数不知道您将其结果转换为什么。 malloc 函数完全依赖于您作为参数提供的大小数。您需要执行 malloc(sizeof(int)) 以获得足够的存储空间来保存 int,例如,不是 0。
【讨论】:
这里有很多半真半假的答案,所以这里是确凿的事实。 malloc() 的手册页说:
如果 size 为 0,则 malloc() 返回 NULL 或稍后可以 成功传递给free()。
这意味着,绝对不能保证malloc(0) 的结果是唯一的或者不是NULL。唯一的保证是由free() 的定义提供的,同样,这是手册页所说的:
如果 ptr 为 NULL,则不执行任何操作。
所以,无论malloc(0) 返回什么,都可以安全地传递给free()。但是NULL 指针也可以。
因此,写作 artist = malloc(0); 绝不比写作好 artist = NULL;
【讨论】:
malloc(0) 可以返回 0x1,free() 可以像对 0x0 一样对 0x1 进行特殊情况检查。
NULL,或唯一指针”。而是“空指针或指向分配空间的指针”。没有 unique 要求。OTOH,返回非唯一的特殊值可能会破坏依赖唯一值的代码。也许是极端情况SO的问题。
man 也可以记录 *nix 中使用的实现定义的形式。在这种情况下它没有,但它仍然不是通用 C 的规范来源。
malloc(0) 对我来说没有任何意义,除非代码依赖于特定于实现的行为。如果代码是可移植的,那么它必须考虑到从malloc(0) 返回的 NULL 不是失败的事实。那么为什么不直接将 NULL 分配给 artist,因为这是一个有效的成功结果,并且代码更少,并且不会导致您的维护程序员花时间来解决这个问题?
malloc(SOME_CONSTANT_THAT_MIGHT_BE_ZERO) 或 malloc(some_variable_which_might_be_zero) 可能有它们的用途,尽管如果值为 0,您必须再次注意不要将 NULL 返回视为失败,但 0 大小应该是可以的。
【讨论】:
为什么你不应该这样做......
由于 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,我在其中举了上面的示例以供进一步阅读。
【讨论】:
诚然,我以前从未见过这种语法,这是我第一次看到这种语法,可以说是函数过度杀伤的经典案例。结合里德的回答,我想指出有一个类似的东西,看起来像一个重载函数realloc:
realloc(foo, size);。当你将一个非 NULL 指针和零大小传递给 realloc 时,realloc 的行为就像你调用了 free(...)realloc(foo, size);。当你传入一个 NULL 指针并且大小不为零时,realloc 的行为就像你调用了 malloc(...)希望这会有所帮助, 最好的祝福, 汤姆。
【讨论】:
要实际回答所提出的问题:没有理由这样做
【讨论】:
在 Windows 中:
void *p = malloc(0); 将在本地堆上分配一个长度为零的缓冲区。返回的指针是一个有效的堆指针。malloc 最终使用默认的 C 运行时堆调用 HeapAlloc,然后调用 RtlAllocateHeap 等。free(p); 使用 HeapFree 释放堆上的 0 长度缓冲区。不释放它会导致内存泄漏。【讨论】:
它实际上非常有用,而且(显然,恕我直言),返回 NULL 指针的允许行为被破坏了。动态指针不仅对它指向的东西有用,而且它的地址是唯一的。返回 NULL 会删除第二个属性。我编写的所有嵌入式 malloc(事实上经常发生)都有这种行为。
【讨论】:
不确定,根据我发现的一些random malloc source 代码,输入 0 会导致返回值为 NULL。因此,将艺术家指针设置为 NULL 是一种疯狂的方式。
http://www.raspberryginger.com/jbailey/minix/html/lib_2ansi_2malloc_8c-source.html
【讨论】:
malloc(0) 将返回 NULL 或可以正确传递给 free 的有效指针。尽管看起来它指向的内存是无用的,或者它不能被写入或读取,但这并不总是正确的。 :)
int *i = malloc(0);
*i = 100;
printf("%d", *i);
我们预计这里会出现分段错误,但令人惊讶的是,这会打印 100!这是因为当我们第一次调用 malloc 时 malloc 实际上会要求大量内存。此后对 malloc 的每次调用都会使用该大块中的内存。只有在那个大块结束后,才会请求新的内存。
使用 malloc(0):如果您处于希望后续 malloc 调用更快的情况,调用 malloc(0) 应该为您完成(边缘情况除外)。
【讨论】:
*i 在您的情况下可能不会崩溃,但它仍然是未定义的行为。当心鼻恶魔!
malloc(0) 的用途。在返回非 NULL 值的那些实现中,尤其是在 DEBUG 构建中,它可能分配的比您要求的更多,并为您提供刚刚超过其内部标头的指针。如果您在一系列分配之前和之后获得了实际内存使用情况,这可以让您感觉。例如:void* before = malloc(0); ... void* after = malloc(0); long long total = after - before; 或类似的。
malloc(0)。你能说一下你指的是哪一章吗?提供准确的报价也很好。
这是使用valgrind内存检查工具运行后的分析。
==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
这是我的示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
//int i;
char *p1;
p1 = (char *)malloc(0);
printf("p1 = %p\n", p1);
free(p1);
return 0;
}
默认分配 1024 字节。如果我增加 malloc 的大小,分配的字节数会增加 1025 以此类推。
【讨论】:
根据Reed Copsey的回答和 malloc 的手册页,我写了一些例子来测试。我发现 malloc(0) 总是会给它一个独特的价值。 看我的例子:
char *ptr;
if( (ptr = (char *) malloc(0)) == NULL )
puts("Got a null pointer");
else
puts("Got a valid pointer");
输出将是“Got a valid pointer”,这意味着ptr 不为空。
【讨论】:
只是为了纠正这里的错误印象:
artist = (char *) malloc(0); 永远不会返回NULL;它与artist = NULL; 不同。编写一个简单的程序并将artist 与NULL 进行比较。 if (artist == NULL) 为假,if (artist) 为真。
【讨论】:
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 将采用 char 的 0 到 255 之间的值,因为它被声明为 unsigned int。
【讨论】:
malloc() 对演员一无所知(这实际上完全是 C 语言流利的)。取消引用 malloc(0) 的返回值将调用未定义的行为。