MALLOC - Linux手册页
Linux程序员手册 第3部分
更新日期: 2020-06-09
名称
malloc,free,calloc,realloc,reallocarray-分配和释放动态内存
语法
#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); void *reallocarray(void *ptr, size_t nmemb, size_t size);
glibc的功能测试宏要求(请参阅feature_test_macros(7)):
reallocarray():
从glibc 2.29开始:
_DEFAULT_SOURCE
Glibc 2.28及更早版本:
_GNU_SOURCE
说明
malloc()函数分配大小字节,并返回指向分配的内存的指针。内存未初始化。如果size为0,则malloc()返回NULL或一个唯一的指针值,该值以后可以成功传递给free()。
free()函数释放ptr指向的内存空间,该内存空间必须已由先前对malloc(),calloc()或realloc()的调用返回。否则,或者如果之前已经调用过free(ptr),则会发生未定义的行为。如果ptr为NULL,则不执行任何操作。
calloc()函数为每个大小为字节的nmemb元素数组分配内存,并返回指向已分配内存的指针。内存设置为零。如果nmemb或size为0,则calloc()返回NULL或一个唯一的指针值,该值以后可以成功传递给free()。如果nmemb和size的乘积将导致整数溢出,则calloc()将返回错误。相比之下,在对malloc()的以下调用中将不会检测到整数溢出,结果将分配大小错误的内存块:
malloc(nmemb * size);
realloc()函数将ptr指向的内存块的大小更改为大小字节。从区域开始到新旧大小的最小值之间的内容将保持不变。如果新的大小大于旧的大小,则不会初始化添加的内存。如果ptr为NULL,则对于所有size值,该调用等效于malloc(size);否则,该调用等效于malloc(size)。如果size等于零,并且ptr不为NULL,则该调用等效于free(ptr)。除非ptr为NULL,否则它必须已经由对malloc(),calloc()或realloc()的更早调用返回了。如果指向的区域已移动,则执行free(ptr)。
reallocarray()函数将ptr指向的内存块的大小更改为足以容纳nmemb元素数组(每个元素均为大小字节)的大小。相当于通话
realloc(ptr,nmemb * size);
但是,与该realloc()调用不同,在乘法将溢出的情况下,reallocarray()安全地失败。如果发生此类溢出,则reallocarray()返回NULL,将errno设置为ENOMEM,并使原始内存块保持不变。
返回值
malloc()和calloc()函数返回一个指向已分配内存的指针,该指针适合于任何内置类型。错误时,这些函数将返回NULL。成功调用大小为零的malloc()或成功调用nmemb或大小等于零的calloc()也可能返回NULL。
free()函数不返回任何值。
realloc()函数返回一个指向新分配的内存的指针,该指针适合于任何内置类型,如果请求失败,则为NULL。如果分配未移动(例如,有空间可以就地扩展分配),则返回的指针可能与ptr相同,或者如果分配已移动到新地址,则返回的指针可能与ptr不同。如果size等于0,则返回NULL或适合传递给free()的指针。如果realloc()失败,则原始块保持不变;它不会被释放或移动。
成功后,reallocarray()函数将返回一个指向新分配的内存的指针。失败时,它将返回NULL,并且原始内存块保持不变。
错误说明
calloc(),malloc(),realloc()和reallocarray()可能因以下错误而失败:
- ENOMEM
- 内存不足。应用程序可能达到了getrlimit(2)中描述的RLIMIT_AS或RLIMIT_DATA限制。
版本
reallocarray()首次出现在2.26版的glibc中。
属性
有关本节中使用的术语的说明,请参见attribute(7)。
Interface | Attribute | Value |
malloc(),free(), calloc(),realloc() | Thread safety | MT-Safe |
遵循规范
malloc(),free(),calloc(),realloc():POSIX.1-2001,POSIX.1-2008,C89,C99。
reallocarray()是一个非标准扩展,最早出现在OpenBSD 5.6和FreeBSD 11.0中。
备注
默认情况下,Linux遵循乐观的内存分配策略。这意味着当malloc()返回非NULL时,不能保证内存确实可用。万一发现系统内存不足,OOM杀手将杀死一个或多个进程。有关更多信息,请参见proc(5)中对/ proc / sys / vm / overcommit_memory和/ proc / sys / vm / oom_adj的描述,以及Linux内核源文件Documentation / vm / overcommit-accounting.rst。
通常,malloc()使用sbrk(2)从堆中分配内存,并根据需要调整堆的大小。当分配大于MMAP_THRESHOLD字节的内存块时,glibc malloc()实现使用mmap(2)将内存分配为私有匿名映射。 MMAP_THRESHOLD默认为128 kB,但可以使用mallopt(3)进行调整。在Linux 4.7之前,使用mmap(2)执行的分配不受RLIMIT_DATA资源限制的影响;从Linux 4.7开始,对使用mmap(2)执行的分配也强制执行此限制。
为了避免多线程应用程序中的损坏,互斥锁在内部用于保护这些功能使用的内存管理数据结构。在线程同时分配和释放内存的多线程应用程序中,这些互斥锁可能存在争用。为了可伸缩地处理多线程应用程序中的内存分配,如果检测到互斥争用,则glibc会创建其他内存分配区域。每个区域都是系统在内部分配的较大内存区域(使用brk(2)或mmap(2)),并使用自己的互斥锁进行管理。
失败时,SUSv2需要malloc(),calloc()和realloc()才能将errno设置为ENOMEM。 Glibc假定已经完成了(这些例程的glibc版本也可以做到这一点)。如果使用未设置errno的私有malloc实现,则某些库例程可能会在没有errno原因的情况下失败。
malloc(),calloc(),realloc()或free()中的崩溃几乎总是与堆损坏有关,例如溢出分配的块或两次释放相同的指针。
malloc()实现可通过环境变量进行调整;有关详细信息,请参见mallopt(3)。
另外参见
valgrind(1),brk(2),mmap(2),alloca(3),malloc_get_state(3),malloc_info(3),malloc_trim(3),malloc_usable_size(3),mallopt(3),mcheck(3), mtrace(3),posix_memalign(3)
有关GNU C库实现的详细信息,请参见
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。