52

很简单的问题,我做了以下程序:

#include <stdlib.h>
int main(int argc, char ** argv)
{
    void * ptr;
    ptr = malloc(0);
    free(ptr);
}

它不会在我的机器上出现段错误。它是 stdlib malloc 和免费的可移植行为,还是我在找麻烦?

编辑:似乎不可移植的是malloc返回的值。问题是关于 malloc(0) + free 组合,而不是 ptr 的值。

4

7 回答 7

69

行为是实现定义的,您将收到 NULL 指针或地址。然而,为接收到的指针调用 free 应该不会导致问题,因为:

  • free(NULL) 没问题,没做任何操作
  • free(address) 没问题,如果地址是从 malloc (或其他像 calloc 等)收到的
于 2009-07-02T08:33:04.047 回答
34

允许返回 NULL,并且允许返回您无法取消引用的非 NULL 指针。这两种方式都受到标准(7.20.3)的认可:

如果请求的空间大小为零,则行为是实现定义的:要么返回空指针,要么行为好像大小是某个非零值,但返回的指针不应用于访问对象.

于 2009-07-02T08:30:35.923 回答
4

对不起,我应该阅读手册页:

malloc()分配 size 字节并返回指向已分配内存的指针。内存没有被清除。如果 size 为 0,则 malloc() 返回 NULL 或稍后可以成功传递给 free() 的唯一指针值。

free() 释放 ptr 指向的内存空间,该内存空间必须由先前对 malloc()、calloc() 或 realloc() 的调用返回。否则,或者如果之前已经调用过 free(ptr),则会发生未定义的行为。如果 ptr 为 NULL,则不执行任何操作。

至少对于 gnu libc 来说似乎是这样的

于 2009-07-02T08:31:00.133 回答
3

根据c标准

7.20.3 如果请求的空间大小为零,则行为由实现定义:要么返回空指针,要么行为好像大小是某个非零值,但返回的指针不得用于访问一个东西。

于 2009-07-02T08:31:37.903 回答
0

更新考虑到 libt & Pax 的评论:

调用 malloc(0) 的行为取决于实现,或者换句话说,不可移植和未定义。

链接到CFaq问题以获取更多详细信息。

于 2009-07-02T08:31:13.240 回答
0

虽然它可能是合法的 C/C++,但它预示着更大的问题。我通常称之为“指针倾斜”。

请参阅“不要对 malloc(0) 或 calloc(0) 的结果做出假设”,https://www.securecoding.cert.org/confluence/display/seccode/VOID+MEMxx-A.+Do+not+ make+assumptions+about+the+result+of+malloc%280%29+or+calloc%280%29

于 2010-08-24T16:24:16.293 回答
-3

根据我的经验,我看到 malloc (0) 返回一个可以释放的指针。但是,这会在以后的 malloc() 语句中导致 SIGSEGV。这是高度随机的。

当我添加一个检查时,如果要分配的大小为零,则不调用 malloc,我摆脱了这个。

所以,我建议不要为大小 0 分配内存。

-阿舒托什

于 2013-06-04T06:34:20.827 回答