很简单的问题,我做了以下程序:
#include <stdlib.h>
int main(int argc, char ** argv)
{
void * ptr;
ptr = malloc(0);
free(ptr);
}
它不会在我的机器上出现段错误。它是 stdlib malloc 和免费的可移植行为,还是我在找麻烦?
编辑:似乎不可移植的是malloc返回的值。问题是关于 malloc(0) + free 组合,而不是 ptr 的值。
行为是实现定义的,您将收到 NULL 指针或地址。然而,为接收到的指针调用 free 应该不会导致问题,因为:
允许返回 NULL,并且允许返回您无法取消引用的非 NULL 指针。这两种方式都受到标准(7.20.3)的认可:
如果请求的空间大小为零,则行为是实现定义的:要么返回空指针,要么行为好像大小是某个非零值,但返回的指针不应用于访问对象.
对不起,我应该阅读手册页:
malloc()分配 size 字节并返回指向已分配内存的指针。内存没有被清除。如果 size 为 0,则 malloc() 返回 NULL 或稍后可以成功传递给 free() 的唯一指针值。
free() 释放 ptr 指向的内存空间,该内存空间必须由先前对 malloc()、calloc() 或 realloc() 的调用返回。否则,或者如果之前已经调用过 free(ptr),则会发生未定义的行为。如果 ptr 为 NULL,则不执行任何操作。
至少对于 gnu libc 来说似乎是这样的
根据c标准
7.20.3 如果请求的空间大小为零,则行为由实现定义:要么返回空指针,要么行为好像大小是某个非零值,但返回的指针不得用于访问一个东西。
虽然它可能是合法的 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。
根据我的经验,我看到 malloc (0) 返回一个可以释放的指针。但是,这会在以后的 malloc() 语句中导致 SIGSEGV。这是高度随机的。
当我添加一个检查时,如果要分配的大小为零,则不调用 malloc,我摆脱了这个。
所以,我建议不要为大小 0 分配内存。
-阿舒托什