malloc(0) 返回什么?
malloc(0)
返回什么?
realloc(malloc(0),0)
的答案是否相同?
#include<stdio.h>
#include<malloc.h>
int main()
{
printf("%p\n", malloc(0));
printf("%p\n", 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\n", realloc(ptr, 1024));
return 0;
}
编辑:
以下代码为每次迭代输出“可能” 。为什么它不应该失败?
#include<stdio.h>
#include<malloc.h>
int main()
{
int i;
void *ptr;
printf("Testing using BRUTE FORCE\n");
for (i=0; i<65000; i++)
{
ptr = malloc(0);
if (ptr == realloc(ptr, 1024))
printf("Iteration %d: possible\n", i);
else
{
printf("Failed for iteration %d\n", i);
break;
}
}
return 0;
}
What does malloc(0)
return?
Would the answer be same for realloc(malloc(0),0)
?
#include<stdio.h>
#include<malloc.h>
int main()
{
printf("%p\n", malloc(0));
printf("%p\n", realloc(malloc(0), 0));
return 0;
}
Output from Linux GCC:
manav@manav-workstation:~$ gcc -Wall mal.c
manav@manav-workstation:~$ ./a.out
0x9363008
(nil)
manav@manav-workstation:~$
The output keep changing everytime for malloc(0)
. Is this a standard answer? And why would anyone be interested in getting such a pointer, other than academic research?
EDIT:
If malloc(0)
returns dummy pointer, then how does following works:
int main()
{
void *ptr = malloc(0);
printf("%p\n", realloc(ptr, 1024));
return 0;
}
EDIT:
The following code outputs "possible" for every iteration. Why should it not fail ?
#include<stdio.h>
#include<malloc.h>
int main()
{
int i;
void *ptr;
printf("Testing using BRUTE FORCE\n");
for (i=0; i<65000; i++)
{
ptr = malloc(0);
if (ptr == realloc(ptr, 1024))
printf("Iteration %d: possible\n", i);
else
{
printf("Failed for iteration %d\n", i);
break;
}
}
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
其他人已经回答了
malloc(0)
的工作原理。我将回答您提出的尚未得到解答的问题之一(我认为)。问题是关于 realloc(malloc(0), 0) 的:标准对于
realloc(ptr, size)
是这么说的:ptr
是NULL
,它的行为就像malloc(size)
code>,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
code> 表示失败。这将导致类似的调用:realloc(NULL, 0)
,这相当于malloc(0)
,它可能返回也可能不返回NULL< /代码>。
我不确定 C99 中的遗漏是否是一个疏忽,或者是否意味着在 C99 中,
realloc(ptr, 0)
对于非NULL
ptr 不等于
free(ptr)
。我刚刚用gcc -std=c99
尝试过,上面相当于free(ptr)
。编辑:我想我明白您的困惑是什么:
让我们看一下示例代码中的片段:
上面与
malloc(0) == realloc(malloc(0) 不同,1024)
。在第二个中,malloc()
调用进行了两次,而在第一个中,您将先前分配的指针传递给realloc()
。我们先分析第一段代码。假设
malloc(0)
在成功时不返回NULL
,则ptr
具有有效值。当您执行realloc(ptr, 1024)
时,realloc()
基本上会为您提供一个大小为 1024 的新缓冲区,并且ptr
变为无效的。符合要求的实现可能会返回与 ptr 中已有的地址相同的地址。因此,您的if
条件可能会返回 true。 (但是请注意,在realloc(ptr, 1024)
之后查看ptr
的值可能是未定义的行为。)现在您问的问题是:
malloc(0 ) == realloc(malloc(0), 1024)
。在本例中,我们假设左侧和右侧的malloc(0)
均返回非NULL
。那么,它们就保证是不同的。此外,LHS 上malloc()
的返回值尚未被free()
释放,因此任何其他malloc()
,calloc()
或realloc()
可能不会返回该值。这意味着,如果您将条件写为:您将不会在输出中看到
possible
(除非malloc()
和realloc()
失败并返回NULL
)。在 OS X 上,我的代码运行时没有输出任何内容。在 Linux 上,它打印
possible, OK
。Others have answered how
malloc(0)
works. I will answer one of the questions that you asked that hasn't been answered yet (I think). The question is aboutrealloc(malloc(0), 0)
:The standard says this about
realloc(ptr, size)
:ptr
isNULL
, it behaves likemalloc(size)
,ptr
is notNULL
), it deallocates the old object pointer to byptr
and returns a pointer to a new allocated buffer. But ifsize
is 0, C89 says that the effect is equivalent tofree(ptr)
. Interestingly, I can't find that statement in C99 draft (n1256 or n1336). In C89, the only sensible value to return in that case would beNULL
.So, there are two cases:
malloc(0)
returnsNULL
on an implementation. Then yourrealloc()
call is equivalent torealloc(NULL, 0)
. That is equivalent tomalloc(0)
from above (and that isNULL
in this case).malloc(0)
returns non-NULL
. Then, the call is equivalent tofree(malloc(0))
. In this case,malloc(0)
andrealloc(malloc(0), 0)
are not equivalent.Note that there is an interesting case here: in the second case, when
malloc(0)
returns non-NULL
on success, it may still returnNULL
to indicate failure. This will result in a call like:realloc(NULL, 0)
, which would be equivalent tomalloc(0)
, which may or may not returnNULL
.I am not sure if the omission in C99 is an oversight or if it means that in C99,
realloc(ptr, 0)
for non-NULL
ptr
is not equivalent tofree(ptr)
. I just tried this withgcc -std=c99
, and the above is equivalent tofree(ptr)
.Edit: I think I understand what your confusion is:
Let's look at a snippet from your example code:
The above is not the same as
malloc(0) == realloc(malloc(0), 1024)
. In the second, themalloc()
call is made twice, whereas in the first, you're passing a previously allocated pointer torealloc()
.Let's analyze the first code first. Assuming
malloc(0)
doesn't returnNULL
on success,ptr
has a valid value. When you dorealloc(ptr, 1024)
,realloc()
basically gives you a new buffer that has the size 1024, and theptr
becomes invalid. A conforming implementation may return the same address as the one already inptr
. So, yourif
condition may return true. (Note, however, looking at the value ofptr
afterrealloc(ptr, 1024)
may be undefined behavior.)Now the question you ask:
malloc(0) == realloc(malloc(0), 1024)
. In this case, let's assume that both themalloc(0)
on the LHS and RHS returns non-NULL
. Then, they are guaranteed to be different. Also, the return value frommalloc()
on the LHS hasn't beenfree()
d yet, so any othermalloc()
,calloc()
, orrealloc()
may not return that value. This means that if you wrote your condition as:you won't see
possible
on the output (unless bothmalloc()
andrealloc()
fail and returnNULL
).On OS X, my code didn't output anything when I ran it. On Linux, it prints
possible, OK
.就 C99 而言,
malloc(0)
是实现定义的。来自 C99 [第 7.20.3 节]
malloc(0)
is Implementation Defined as far as C99 is concerned.From C99 [Section 7.20.3]
在 C89 中,malloc(0) 取决于实现 - 我不知道 C99 是否已修复此问题。在 C++ 中,使用:
定义良好 - 您将获得一个有效的非空指针。当然,您不能使用指针来访问它所指向的内容而不调用未定义的行为。
至于为什么存在这种情况,它对于某些算法来说很方便,并且意味着您不需要在代码中进行零值测试。
In C89, malloc(0) is implementation dependent - I don't know if C99 has fixed this or not. In C++, using:
is well defined - you get a valid, non-null pointer. Of course, you can't use the pointer to access what it points to without invoking undefined behaviour.
As to why this exists, it is convenient for some algorithms, and means you don't need to litter your code with tests for zero values.
C99标准
C99 standard
comp.lang.c 常见问题解答有 以下说:
因此,最好避免使用
malloc(0)
。The comp.lang.c FAQ has the following to say:
So, it's probably best to avoid using
malloc(0)
.有一点还没有人愿意谈论,在你的第一个程序中,长度为 0 的
realloc
与free
是一样的。来自 Solaris 手册页:
如果一个人不知道这可能会带来糟糕的惊喜(发生在我身上)。
One point nobody cared to talk about yet, in your first program is that
realloc
with length 0 is the same thing asfree
.from the Solaris man page:
If one doesn't know that it can be a source of bad surprise (happened to me).
参见 C99,第 7.20.3 节:
这对于所有三个分配函数(即
calloc()
、malloc()
和realloc()
)都有效。See C99, section 7.20.3:
This is valid for all three allocation functions (ie
calloc()
,malloc()
andrealloc()
).我认为这取决于。
我检查了 Visual Studio 2005 源代码并在 _heap_alloc 函数中看到了这一点:
我认为在许多情况下您可能需要一个有效的指针,即使在要求零字节时也是如此。
这是因为这种一致的行为使检查指针变得更加容易,因为: 如果您有一个非 NULL 指针,那么就可以了;如果你有一个 NULL 指针,你可能会遇到问题。
这就是为什么我认为大多数实现都会返回一个有效的指针,即使在要求零字节时也是如此。
I think it depends.
I checked the Visual Studio 2005 sources and saw this in the _heap_alloc function:
I think that in many cases you may want a valid pointer, even when asking for zero bytes.
This is because this consistent behavior makes it easier to check your pointers because: if you have a non-NULL pointer it's OK; if you have a NULL pointer you probably have a problem.
That's why I think that most implementations will return a valid pointer, even when asking for zero bytes.
我不知道你所说的“虚拟指针”是什么意思。如果
malloc(0)
返回非 NULL,则ptr
是指向大小为零的内存块的有效指针。malloc
实现以特定于实现的方式保存此信息。 realloc 知道(特定于实现的)方法来确定 ptr 指向大小为零的内存块。(
malloc
/realloc
/free
如何做到这一点是特定于实现的。一种可能是分配比请求多 4 个字节并存储大小在这种情况下,((int *)ptr)[-1]
将给出内存块大小,即0
。从您的代码来看,它仅供realloc
和free
使用)。I don't know what you mean by "dummy pointer". If
malloc(0)
returns non-NULL, thenptr
is a valid pointer to a memory block of size zero. Themalloc
implementation saves this information in an implementation-specific way.realloc
knows the (implementation-specific) way to figure out thatptr
points to a memory block of size zero.(How
malloc
/realloc
/free
do this is implementation-specific. One possibility is to allocate 4 bytes more than requested and store the size just before the memory block. In that case,((int *)ptr)[-1]
would give the memory block size, which is0
. You should never do this from your code, it's only for use byrealloc
andfree
).