合法的malloc(0)和free(0)

Last Updated: 2024-01-08 02:14:06 Monday

-- TOC --

malloc(0)是可以成功的:

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

int main(void) {
    char* p = malloc(0);
    printf("%p\n", p);
    if (p == NULL)
        printf("null\n");
    free(p);
    return 0;
}

以上测试代码,能够将一个有效的地址打印出来。

malloc(0)没有实际意义,返回的地址是可用的地址,但是可用长度为0,只要写入,理论上就是越界!malloc(0)得到的指针,也必须free!

有网友翻出了glibc中malloc接口的注释,说得更清楚:

malloc(size_t n)

Returns a pointer to a newly allocated chunk of at least n bytes, or null if no space is available. Additionally, on failure, errno is set to ENOMEM on ANSI C systems.

If n is zero, malloc returns a minumum-sized chunk. (The minimum size is 16 bytes on most 32bit systems, and 24 or 32 bytes on 64bit systems.) On most systems, size_t is an unsigned type, so calls with negative arguments are interpreted as requests for huge amounts of space, which will often fail. The maximum supported value of n differs across systems, but is in all cases less than the maximum representable value of a size_t.

malloc(0)会返回几十个字节,指针对应的申请大小,就存放在这里面。这就是为什么free的时候,不需要传入指针指向的大小,运行时系统自动就能够知道,这个指针指向空间的大小。

free一个值为0的指针,合法!free接口内部会做检查。free之后将指针值设置为0,也可预防double free。


malloc的实现,调用了系统调用brkmmap,这里就体现了非常重要的运行时概念!运行时库封装了系统调用,为进程管理了虚拟地址空间的内存,用户编写的代码,必须要与运行时库进行链接,才能在OS中被加载运行。

malloc的实现,对于申请小于128K内存时,调用brk系统调用,推高__enddata指针。这部分容易产生内存碎片,也会不时地触发内存紧缩,因为只有一个__enddata指针。对于大于128K时的申请,调用mmap。本质是,malloc和free将内存管理的很多细节封装了起来,用户进程代码就不需要关心了。因此,malloc(0)和free(0)是合法的调用。

跟很多框架一样,运行时库也是个框架,只不过它比较特殊,它紧贴在OS系统调用上面,为每一个进程服务。运行时库大大降低了程序员写代码的难度,反过来就是增加某个OS的受欢迎程度!(OS也是个框架,编写kernel module需要符合OS框架的规范)

本文链接:https://cs.pynote.net/sf/c/202302273/

-- EOF --

-- MORE --