首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Linux C 庫函數大全:內存控制函數詳解與實戰案例

     編輯:關於C語言

前言:內存管理——C 語言程序員的核心基本功

在 Linux 系統編程中,動態內存的分配、釋放、映射、對齊直接決定程序的穩定性與性能。本文系統整理 stdlib.h、malloc.h、sys/mman.h 等頭文件中的核心內存控制函數,附帶原型、語義、錯誤處理、實戰代碼與避坑指南。

一、 堆內存分配家族

1. 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);

2. 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"); // 安全

3. 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;

4. free:釋放歸還

void free(void *ptr);
  • ptr 必須來自 malloc/calloc/realloc,否則未定義行為。
  • free(NULL) 安全無操作 (標準保證)。
  • 釋放後指針成「懸空指針」,**嚴禁再次訪問**,良習:free(p); p = NULL;。

二、 內存映射:mmap / munmap

將文件/設備直接映射到進程地址空間,**零拷貝** 讀寫,適合大文件、進程間共享內存。

1. mmap

void *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);

2. munmap

int munmap(void *addr, size_t length);
  • 解除映射,**不關閉 fd** (需單獨 close)。
  • 進程退出/ exec 時自動解除。

三、 頁面與邊界查詢

  • getpagesize():返回系統頁大小 (x86 通常 4096)。
  • sbrk/brk:底層堆擴展接口 (glibc malloc 內部使用,**應用層勿直接調用**)。

四、 避坑總結:內存管理鐵律

  1. 分配必檢 NULL:OOM 時崩潰優於邏輯錯誤。
  2. 釋放必配對:一 malloc 對一 free,mmap 對 munmap。
  3. 釋放後置 NULL:防雙重釋放/使用後釋放。
  4. 邊界不越界:valgrind --leak-check=full、AddressSanitizer 定期檢測。
  5. 對齊用 posix_memalign/aligned_alloc:SIMD/DMA/硬件交互場景必備。
  6. 大塊優先 mmap:>128KB 分配 glibc 自動走 mmap,減少堆碎片。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved