malloc(0) 返回什么?[重复]
- 2024-10-14 08:40:00
- admin 原创
- 74
问题描述:
返回什么malloc(0)
?
答案是否相同realloc(malloc(0),0)
?
#include<stdio.h>
#include<malloc.h>
int main()
{
printf("%p
", malloc(0));
printf("%p
", realloc(malloc(0), 0));
return 0;
}
Linux GCC 的输出:
manav@manav-workstation:~$ gcc -Wall mal.c
manav@manav-workstation:~$ ./a.out
0x9363008
(nil)
manav@manav-workstation:~$
每次输出都会发生变化malloc(0)
。这是标准答案吗?除了学术研究之外,为什么有人会对获得这样的指针感兴趣?
编辑:
如果malloc(0)
返回虚拟指针,那么以下工作如何进行:
int main()
{
void *ptr = malloc(0);
printf("%p
", realloc(ptr, 1024));
return 0;
}
编辑:
以下代码每次迭代都会输出“可能”。为什么它不会失败?
#include<stdio.h>
#include<malloc.h>
int main()
{
int i;
void *ptr;
printf("Testing using BRUTE FORCE
");
for (i=0; i<65000; i++)
{
ptr = malloc(0);
if (ptr == realloc(ptr, 1024))
printf("Iteration %d: possible
", i);
else
{
printf("Failed for iteration %d
", i);
break;
}
}
return 0;
}
解决方案 1:
其他人已经回答了如何malloc(0)
工作。我将回答您提出的尚未回答的一个问题(我认为)。问题是关于realloc(malloc(0), 0)
:
返回什么
malloc(0)
?答案是否相同realloc(malloc(0),0)
?
标准是这样说的realloc(ptr, size)
:
如果
ptr
是NULL
,它的行为就像malloc(size)
,否则(
ptr
不是NULL
),它会释放指向的旧对象指针ptr
并返回指向新分配缓冲区的指针。但如果size
是 0,C89 表示效果相当于free(ptr)
。有趣的是,我在 C99 草案(n1256 或 n1336)中找不到该语句。在 C89 中,在这种情况下返回的唯一合理值是NULL
。
因此,有两种情况:
malloc(0)
返回NULL
实现。那么您的realloc()
调用相当于realloc(NULL, 0)
。这相当于malloc(0)
上面的(在本例中是NULL
)。malloc(0)
返回非NULL
。那么,调用 相当于free(malloc(0))
。在这种情况下,malloc(0)
和realloc(malloc(0), 0)
不等价。
请注意,这里有一个有趣的情况:在第二种情况下,当成功时malloc(0)
返回非 时NULL
,它仍可能返回NULL
以指示失败。这将导致类似这样的调用:realloc(NULL, 0)
,这相当于malloc(0)
,它可能返回 ,也可能不返回NULL
。
我不确定 C99 中的遗漏是否是疏忽,或者这是否意味着在 C99 中,realloc(ptr, 0)
非NULL
ptr
不等同于free(ptr)
。我刚刚用 尝试过gcc -std=c99
,上面的内容等同于free(ptr)
。
编辑:我想我明白你的困惑是什么:
让我们看一下示例代码中的一段:
ptr = malloc(0);
if (ptr == realloc(ptr, 1024))
上面的代码与 不同malloc(0) == realloc(malloc(0), 1024)
。在第二个代码中,malloc()
调用了两次,而在第一个代码中,你将一个先前分配的指针传递给realloc()
。
让我们首先分析一下第一个代码。假设成功时malloc(0)
不返回,则具有有效值。当您执行时,基本上会为您提供一个大小为 1024 的新缓冲区,并且变为无效。符合要求的实现可能会返回与中已有的地址相同的地址。因此,您的条件可能会返回 true。(但请注意,查看after的值可能是未定义的行为。)NULL
`ptrrealloc(ptr, 1024)
realloc()ptr
ptrif
ptr`realloc(ptr, 1024)
现在你要问的问题是:malloc(0) == realloc(malloc(0), 1024)
。在这种情况下,我们假设malloc(0)
LHS 和 RHS 上的 都返回非NULL
。那么,它们肯定是不同的。此外,malloc()
LHS 上的 返回值尚未被free()
d,因此任何其他malloc()
、calloc()
或 都realloc()
可能不会返回该值。这意味着如果你将条件写为:
if (malloc(0) == realloc(malloc(0), 1024)
puts("possible");
您不会possible
在输出中看到(除非malloc()
和都realloc()
失败并返回NULL
)。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
void *p1;
void *p2;
p1 = malloc(0);
p2 = realloc(p1, 1024);
if (p1 == p2)
puts("possible, OK");
/* Ignore the memory leaks */
if (malloc(0) == realloc(malloc(0), 1024))
puts("shouldn't happen, something is wrong");
return 0;
}
在 OS X 上,运行我的代码时没有输出任何内容。在 Linux 上,它会打印possible, OK
。
解决方案 2:
malloc(0)
就 C99 而言是实现定义的。
来自C99 [第 7.20.3 节]
通过连续调用 calloc、malloc 和 realloc 函数分配的存储的顺序和连续性 未指定。如果分配成功,则返回适当对齐的指针,以便可以将其分配给指向任意类型对象的指针,然后用于访问分配空间中的此类对象或此类对象数组(直到明确释放空间)。分配对象的生命周期从分配一直延续到释放。每次这样的分配都会产生一个指向与任何其他对象不相交的对象的指针。返回的指针指向分配空间的起始(最低字节地址)。如果无法分配空间,则返回一个空指针。 如果请求的空间大小为零,则行为是实现定义的:要么返回一个空指针,要么行为就像大小是某个非零值,只是返回的指针不能用于访问对象。
解决方案 3:
在 C89 中,malloc(0) 依赖于实现 - 我不知道 C99 是否已修复此问题。在 C++ 中,使用:
char * p = new char[0];
定义良好 - 您获得一个有效、非空的指针。当然,您不能使用该指针访问其指向的内容,否则会引发未定义的行为。
至于为什么存在这种情况,它对于某些算法来说很方便,并且意味着您不需要在代码中塞满对零值的测试。
解决方案 4:
C99 标准
如果无法分配空间,则返回空指针。如果请求的空间大小为零,则行为由实现定义:要么返回空指针,要么行为就像大小是某个非零值一样,只是返回的指针不得用于访问对象。
解决方案 5:
comp.lang.c常见问题解答如下:
ANSI/ISO 标准规定它可以执行上述任一操作;行为由实现定义(参见问题 11.33)。可移植代码必须注意不要调用 malloc(0),或者为可能返回 null 做好准备。
因此,最好避免使用malloc(0)
。
解决方案 6:
在您的第一个程序中,还没有人愿意谈论的一点是,realloc
长度 0 与 是相同的free
。
来自 Solaris 手册页:
该
realloc()
函数将 指向的块的大小更改为ptr
字节size
,并返回指向(可能已移动)块的指针。内容将保持不变,直到新旧大小中较小者。如果ptr
为NULL
,则对于指定的大小,realloc()
其行为类似。如果 为
且 不是空指针,则指向的空间可供应用程序进一步分配,但不会返回给系统。只有在应用程序终止时,内存才会返回给系统。malloc()
`size0
ptr`
如果人们不知道,这可能会成为一个不好的惊喜的根源(就发生在我身上)。
解决方案 7:
参见 C99,第 7.20.3 节:
如果请求的空间大小为零,则行为由实现定义:要么返回一个空指针,要么行为就好像大小是某个非零值,但返回的指针不能用于访问对象。
calloc()
这对于所有三个分配函数(即、malloc()
和)都有效realloc()
。
解决方案 8:
我认为这取决于情况。我检查了 Visual Studio 2005 源代码,并在 _heap_alloc 函数中看到了这一点:
if (size == 0)
size = 1;
我认为在很多情况下,你可能想要一个有效的指针,即使请求零字节。这是因为这种一致的行为使检查指针变得更容易,因为:如果你有一个非 NULL 指针,那就没问题;如果你有一个 NULL 指针,那么你可能有问题。这就是为什么我认为大多数实现都会返回一个有效的指针,即使请求零字节。
解决方案 9:
如果 malloc(0) 返回虚拟指针,那么以下工作如何进行:
void *ptr = malloc(0);
`printf("%p
", realloc(ptr, 1024));`
我不知道您说的“虚拟指针”是什么意思。如果malloc(0)
返回非 NULL,则为ptr
指向大小为零的内存块的有效指针。malloc
实现以特定于实现的方式保存此信息。 realloc
知道(特定于实现的)找出指向ptr
大小为零的内存块的方法。
(如何malloc
做到realloc
这free
一点取决于具体实现。一种可能性是分配比请求的多 4 个字节,并将大小存储在内存块之前。在这种情况下,((int *)ptr)[-1]
将给出内存块大小,即0
。您永远不应该在代码中这样做,它仅供realloc
和使用free
)。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件