《Linux/Unix系统编程手册》读书笔记4
《Linux/Unix系统编程手册》读书笔记4
《Linux/Unix系统编程手册》读书笔记 目录
第7章:
内存分配
通过增加堆的大小分配内存,通过提升program break位置的高度来分配内存。
基本学过C语言的都用过malloc来分配内存,而malloc都基于brk()和sbrk()。
#include <unistd.h>
brk( *
*sbrk(intptr_t increment);
brk()系统调用会将program break设置为end_data_segment的位置。成功调用返回0,失败返回-1。
sbrk()系统调用会将program break原来的位置增加increment的大小。成功调用返回原来program break的位置,失败返回(void *)-1。
PS:sbrk(0)返回program break的当前位置。
malloc()函数,C使用该函数在堆上分配和释放内存。
#include <stdlib.h>
*malloc(size_t size);
malloc分配size字节大小的内存。并返回指向新分配的内存的起始位置的指针,该内存未经初始化;失败返回NULL。
通常对返回的指针进行显式类型转换来获得自己想要的类型的指针。
实际上每次调用malloc分配内存时,会额外分配多几个字节来记录这块内存的大小。(如下图所示)
free()函数用来释放内存块。
#include <stdlib.h>
free( *ptr);
free释放ptr指向的内存块,ptr必须是malloc、calloc、realloc返回的指针。
free不会降低program break的位置,而是将该内存添加到空闲内存列表,用于以后malloc使用。
PS:不能对已经调用过free函数的指针,再次调用free,这样会产生错误。
因为malloc分配后的内存会有内存块的长度,所以free会知道这块内存的大小,从而准确的将内存块释放,并放入空闲内存块列表中。
PS:因此不能用free随便释放不是malloc返回的指针。
经过free释放后的内存块结构如下:
其实malloc调用是先查找空闲内存块列表,找到合适的内存块。如果找不到合适的内存块就调用sbrk()来分配更多的内存,为了减少调用sbrk的次数,会分配比size大小更多的内存来增加program break的位置,超出size大小的内存块会放到空闲内存列表。
calloc()函数可以对一组相同的对象分配内存。
#include <stdlib.h>
*calloc(size_t numitems, size_t size);
numitems指定了对象的数量,size指定了每个对象的大小。成功调用返回内存块的起始地址,失败返回NULL。malloc返回的内存不会初始化,而calloc返回的内存块是已初始化。
realloc()函数可以调整一块内存的大小。
#include <stdlib.h>
*realloc( *ptr, size_t size);
ptr是需要调整大小的内存块的指针, size是所需调整大小的期望值。
成功调用会返回指向调整后内存块的指针(位置可能不同),失败返回NULL。
练习:
7-1. 修改程序清单7-1中的程序,在每次执行malloc()后打印出program break的当前至。指定一个较小的内存分配尺寸来运行该程序。这将证明malloc不会在每次调用时都会调用sbrk()来调整program break的位置,而是周期性地分大块内存,并从中将小片内存返回给调用者。
程序清单7-1:
#include MAX_ALLOCS 1000000 main( argc, * * printf( (argc < || strcmp(argv[], ) == usageErr(, argv[ numAllocs = getInt(argv[], GN_GT_0, (numAllocs > cmdLineErr( blockSize = getInt(argv[], GN_GT_0 | GN_ANY_BASE, freeStep = (argc > ) ? getInt(argv[], GN_GT_0, ) : freeMin = (argc > ) ? getInt(argv[], GN_GT_0, ) : freeMax = (argc > ) ? getInt(argv[], GN_GT_0, (freeMax > cmdLineErr( printf(, sbrk( printf( (j = ; j < numAllocs; j++ ptr[j] = (ptr[j] == errExit( printf(, sbrk( printf( (j = freeMin-; j < freeMax; j += printf(, sbrk( } View Code
#include
MAX_ALLOCS 1000000
main( argc, * *
printf(