如果`malloc(0)`返回一个非空指针,我可以将它传递给`free`吗?

pnk*_*lix 43 c malloc free memory-management

我一直在阅读有关malloc当您请求零大小的块时的行为的讨论.

我理解malloc(0)是实现定义的行为,它应该返回一个空指针,或者我仍然不应该访问的非空指针.(这是有道理的,因为不能保证它指向任何可用的内存.)

但是,如果获得这样一个不可访问的非空指针,我是否允许以free通常的方式传递给它?或者这是非法的,因为我得到的指针malloc(0)可能不指向实际分配的内存块?

具体而言,以下代码是否具有明确定义的行为:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int* x = (int*) malloc(0);
    if (x == NULL) {
        printf("Got NULL\n");
        return 0;
    } else {
        printf("Got nonnull %p\n", x);
    }
    free(x); // is calling `free` here okay?
}
Run Code Online (Sandbox Code Playgroud)

apr*_*ori 41

C99标准(实际上是WG14/N1124.委员会草案 - 2005年5月6日.ISO/IEC 9899:TC2)说malloc():

返回的指针指向分配空间的开始(最低字节地址).如果无法分配空间,则返回空指针.如果请求的空间大小为零,则行为是实现定义的:返回空指针,或者行为就像大小是非零值一样,除了返回的指针不应该用于访问对象

和关于free():

否则,如果参数与之前由calloc,malloc或realloc函数返回的指针不匹配,或者如果通过调用free或realloc释放了空间,则行为未定义.

IEEE Std 1003.1-2008(POSIX),2016版说free():

free()函数将导致ptr指向的空间被释放; 也就是说,可供进一步分配.如果ptr是空指针,则不会发生任何操作.否则,如果参数与之前由POSIX.1-2008中的函数返回的指针不匹配,该函数像malloc()一样分配内存,或者如果通过调用free()或realloc()释放空间,行为未定义.

所以,无论*alloc()回报如何,你都可以转而去free().

至于目前的实施malloc():

FreeBSD使用贡献的jemalloc

void *
je_malloc(size_t size)
{
    void *ret;
    size_t usize JEMALLOC_CC_SILENCE_INIT(0);

    if (size == 0)
        size = 1;
    [...]
Run Code Online (Sandbox Code Playgroud)

Apple的libmalloc确实如此

void *
szone_memalign(szone_t *szone, size_t alignment, size_t size)
{
    if (size == 0) {
        size = 1; // Ensures we'll return an aligned free()-able pointer
    [...]
Run Code Online (Sandbox Code Playgroud)

GLIBC也改变了要求的大小; 它正在使用对此宏的调用,并将请求的大小(以字节为单位)作为参数,以将大小与特定边界对齐,或者只是最小分配大小:

#define request2size(req)                                       \
    (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE)  ?         \
    MINSIZE :                                                   \
    ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
Run Code Online (Sandbox Code Playgroud)


Mal*_*ean 24

是的,实际上你必须这样做以避免可能的内存泄漏.

malloc系统通常在指针之前的空间中返回隐藏的控制块,其具有诸如分配大小的信息.如果分配大小为零,则此块仍然存在并占用内存,如果malloc返回非null.

  • @PaulOgilvie你的评论有点混乱; 如果malloc返回NULL,那么你可以将它传递给free (8认同)
  • @PaulOgilvie--这就是标准指定的原因["如果ptr是空指针,则不会发生任何操作."](http://port70.net/~nsz/c/c11/n1570.html#7.22.3.3p2) (4认同)