The Linux Programming Interface
Memory Allocation
(1) 内容
This chapter describes the functions that are used to allocate memory on the heap or the stack.
To allocate memory, C programs normally use the malloc family of functions, which we describe shortly. However, we begin with a description of brk() and sbrk(), upon which the malloc functions are based.
#include <unistd.h>
int brk(void *end_data_segment);
The brk() system call sets the program break to the location specified by end_data_segment. Since virtual memory is allocated in units of pages, end_data_segment is effectively rounded up to the next page boundary.
On success, sbrk() returns the previous address of the program break.
The call sbrk(0) returns the current setting of the program break without changing it.
(02) malloc()函数,分配内存的使用
The malloc function allocates size bytes from the heap and returns a pointer to the start of the newly allocated block of memory.
#include <stdlib.h>
void *malloc(size_t size);
Because malloc() returns void *, we can assign it to any type of C pointer.
(03) free() 释放内存
void free(void *ptr);
The free function deallocates the block of memory pointed to by its ptr argument, which should be an address previously returned by malloc() or others.
(04) 展示free用例
#include "tlpi_hdr.h" #define MAX_ALLOCS 1000000 int main(int argc, char *argv[]) { char *ptr[MAX_ALLOCS]; int freeStep, freeMin, freeMax, blockSize, numAllocs, j; printf("\n"); if (argc < 3 || strcmp(argv[1], "--help") == 0) usageErr("%s num-allocs block-size [step [min [max]]]\n", argv[0]); numAllocs = getInt(argv[1], GN_GT_0, "num-allocs"); if (numAllocs > MAX_ALLOCS) cmdLineErr("num-allocs > %d\n", MAX_ALLOCS); blockSize = getInt(argv[2], GN_GT_0 | GN_ANY_BASE, "block-size"); freeStep = (argc > 3) ? getInt(argv[3], GN_GT_0, "step") : 1; freeMin = (argc > 4) ? getInt(argv[4], GN_GT_0, "min") : 1; freeMax = (argc > 5) ? getInt(argv[5], GN_GT_0, "max") : numAllocs; if (freeMax > numAllocs) cmdLineErr("free-max > num-allocs\n"); printf("Initial program break: p\n", sbrk(0)); printf("Allocating %d * %d bytes\n", numAllocs, blockSize); for (j = 0; j < numAllocs; j++) { ptr[j] = malloc(blockSize); if (ptr[j] == NULL) errExit("malloc"); } printf("Program break is now: p\n", sbrk(0)); printf("Freeing blocks from %d to %d in steps of %d\n", freeMin, freeMax, freeStep); for (j = freeMin - 1; j < freeMax; j += freeStep) free(ptr[j]); printf("After free(), program break is: p\n", sbrk(0)); exit(EXIT_SUCCESS); }输出:wang@wang:~/test/tlpi-dist/lib$ ./free_and_sbrk 1000 10240 2 Initial program break: 0x19fa000 Allocating 1000 * 10240 bytes Program break is now: 0x23c2000 Freeing blocks from 1 to 1000 in steps of 2 After free(), program break is: 0x23c2000 wang@wang:~/test/tlpi-dist/lib$ ./free_and_sbrk 1000 10240 1 1 999 Initial program break: 0xdb6000 Allocating 1000 * 10240 bytes Program break is now: 0x177e000 Freeing blocks from 1 to 999 in steps of 1 After free(), program break is: 0x177e000
(05)malloc实现
The implementation of malloc() is straightforward. It first scans the list of memory blocks previously released by free() in order to find one whose size is larger than or equal to its requirement.
If it is larger, then it is split, so that a block of the correct size is returned to the caller and a smaller free block is left on the free list.
If no block on the free list is large enough, then malloc() calls sbrk() to allocate more memory.
(06)calloc使用
Here is an example of the use of calloc(): struct {/* Some field definitions */ } myStruct; struct myStruct *p; p = calloc(1000, sizeof(struct myStruct)); if (p == NULL) errExit("calloc");(07)realloc函数使用The realloc() function is used to resize (usually enlarge) a block of memory previously allocated by one of the functions in the malloc package.
void *realloc(void *ptr, size_t size);
(08) alloca()
Instead of obtaining memory from the heap, alloca() obtain memory from the stack by increasing the size of the stack frame.
void *alloca(size_t size);
(09) 总结
Using the malloc family of functions, a process can dynamically allocate and release memory on the heap. In considering the implementation of these functions, we saw that various things can go wrong in a program that mishandles the blocks of allocated memory, and we noted that a number of debugging tools are available to help locate the source of such errors.
The alloca() function allocates memory on the stack. This memory is automatically deallocated when the function that calls alloca() returns.
(10)习题