在 Linux 系統編程中,動態內存的分配、釋放、映射、對齊直接決定程序的穩定性與性能。本文系統整理 stdlib.h、malloc.h、sys/mman.h 等頭文件中的核心內存控制函數,附帶原型、語義、錯誤處理、實戰代碼與避坑指南。
malloc:基礎塊分配void *malloc(size_t size);
size 字節,**不初始化** 內容 (殘留垃圾值)。NULL (必須檢查)。free。int *arr = malloc(10 * sizeof(int));
if (!arr) { perror("malloc"); exit(1); }
for (int i=0; i<10; i++) arr[i] = i;
free(arr);
calloc:零初始化陣列分配void *calloc(size_t nmemb, size_t size);
nmemb * size 字節,**自動清零** (等價 malloc + memset(0) 但可能更優化)。int *p = calloc(10, sizeof(int)); // 全 0
char *str = calloc(10, sizeof(char));
strcpy(str, "Hello"); // 安全
realloc:動態調整大小void *realloc(void *ptr, size_t size);
ptr=NULL 等價 malloc;size=0 等價 free (實現定義)。ptr = realloc(ptr, ...) 直接賦值,若失敗返回 NULL 導致原指針丟失 → 內存洩漏。正確寫法:void *tmp = realloc(ptr, new_size);
if (!tmp) { /* 錯誤處理,ptr 仍有效 */ }
else ptr = tmp;
free:釋放歸還void free(void *ptr);
ptr 必須來自 malloc/calloc/realloc,否則未定義行為。free(NULL) 安全無操作 (標準保證)。free(p); p = NULL;。mmap / munmap將文件/設備直接映射到進程地址空間,**零拷貝** 讀寫,適合大文件、進程間共享內存。
mmapvoid *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
prot:PROT_READ|PROT_WRITE|PROT_EXEC|PROT_NONE。flags:MAP_SHARED (寫回文件/進程可見) vs MAP_PRIVATE (COW 私有副本) —— **必二擇一**。MAP_ANONYMOUS:無文件映射 (配合 fd=-1),純內存共享區。offset 必須頁對齊 (通常 4096)。// 映射整個 /etc/passwd 只讀共享
int fd = open("/etc/passwd", O_RDONLY);
struct stat sb; fstat(fd, &sb);
void *map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (map == MAP_FAILED) { perror("mmap"); exit(1); }
printf("%s", (char*)map);
munmap(map, sb.st_size);
close(fd);
munmapint munmap(void *addr, size_t length);
close)。exec 時自動解除。getpagesize():返回系統頁大小 (x86 通常 4096)。sbrk/brk:底層堆擴展接口 (glibc malloc 內部使用,**應用層勿直接調用**)。malloc 對一 free,mmap 對 munmap。valgrind --leak-check=full、AddressSanitizer 定期檢測。posix_memalign/aligned_alloc:SIMD/DMA/硬件交互場景必備。mmap:>128KB 分配 glibc 自動走 mmap,減少堆碎片。