malloc, free, calloc, realloc - 分配及释放动态内存
#include <stdlib.h>
void *malloc(size_t size); void free(void *ptr); void *calloc(size_t nmemb, size_t size); void *realloc(void *ptr, size_t size); |
malloc()函数分配size个字节内存并且返回指向所分配内存的首地址。这块内存没有被初始化。如果size为0,malloc()返回NULL,或者返回一个能被free()成功释放的独特的地址。
free()函数释放ptr所指向的内存空间,ptr必须是malloc(),calloc()或者realloc()函数的返回值。否则,采用free(ptr)后,程序运行结果无定义。或者之前已经调用过一次free(ptr),再调用free(ptr)时,程序运行结果无定义。如果ptr的值为NULL,free(ptr)语句不会有任何操作。
calloc()函数分配连续的nmemb个以size字节为单位的内存单元,并返回这段内存的首地址。这段内存被初始化为0。如果nmemb或者size的值为0,那么calloc()将返回NULL或者返回一个独特的地址值,这个地址值可被free()函数成功的释放。
realloc()函数改变ptr所指内存的内存块到size字节。在新的size字节中,与原内存对应的内存块保存着原内存的内容。如果新分配内存大于原内存,新增的内存不会被初始化。如果ptr为NULL,对于size的所有值realloc()与malloc()功能一样。如果size的值为0,ptr的值不为空,那么调用realloc()函数与调用free(ptr)等效。虽然ptr可以为NULL,但它必须是被之前malloc(), calloc()或者realloc所返回的。如果被指的区域被移除了,那么就说明free(ptr)操作发生了。
malloc()和calloc()函数返回经分配的可以保存各种类型值的内存片段的首地址。如果出错,则返回NULL。当size为0时,调用malloc()函数成功,但返回NULL,当nmemb或者size为0时,调用calloc()函数成功,但返回NULL。
free()函数无返回值。
realloc()函数返回指向新分配内存的地址,这块内存可以保存各种类型的值,这个地址可能和最初的ptr不同,如果realloc()执行失败则返回NULL。如果size值为0,那么realloc()函数会返回NULL或者一个独特的值,NULL或者这个值都可以被free()函数成功释放。如果realloc()函数失败,那么原来的内存原封不动,原来的内存没有被释放或者被改动。
C89, C99
默认下,Linux使用最优内存分配的策略。这就意味着,尽管malloc()没有返回NULL但也不能保证所分配的内存是可用的。如内存的越界,那么这样的进程将会被OOM终止。预了解详情,参见proc(5)下/proc/sys/vm/overcommit memmory以及/proc/sys/vm/oomadj中的描述,也可以参见Linux内核文件Documentation/vm/overcommit accounting。
正常情况下,malloc()从堆中分配内存,并用sbrk(2)来根据需求调整堆内存的大小。当分配的内存块大于MMAP_THRESHOLD字节时,库函数malloc()通过调用mmap(2)来映射一块内存的方式来实现空间的分配。MMAP_THRESHOLD的默认值为128kB,这个值能通过mallopt(3)来调整。用mmap(2)来分配空间不受RLIMIT_DATA资源的限制(参见getrlimit(2))。
为了避免在多线程程序里的内存分配问题,写在函数里面的互斥被用来保护内存管理的数据结构。在多线程程序内,不同的线程都需要分配和释放内存的时候就需要争夺互斥。为实现在多线程程序中分级的处理内存分配,如果检测到对互斥的争夺的话,glibc库提供了额外的内存分配区。每个区都是来自系统(用brk(2)或者mmap(2)分配的),然后各区用自己的互斥来操作这些内存。
UNIX 98标准要求malloc(),calloc()及realloc()在分配内存失败时都设置errno到ENOMEM。Glibc库假设这个要求已经被完成(各个版本的glibc见会完成这段代码);如果你调用自己编写的malloc函数实现内存分配发现没有设置errno时,由于errno里没有被设置故而库里面设置errno到ENOMEM的代码就会执行失败。
在malloc(), calloc(), realloc()及free()函数中引起的系统崩溃一般都是堆内存引起的,如使用分配的堆内存越界,用free()释放同一块内存两次。
最新的Linux库(5.4.23以后)即glibc(2.x)通过环境变量实现了malloc()的可调协功能。具体细节参见mallopt(3)。
这个页面是Linux man-pages工程3.44 的一部分。此工程的描述以及具体信息在http://www.kernel.org/doc/man-pages/.
[2014.11.6 - 13:20]
Try-TNote Over.