Linux開發入門筆記——儲存管理
程式儲存結構與程序結構
程式碼區(text segment)
載入的是可執行檔案程式碼段,其載入到記憶體中的位置由載入器完成。
全域性初始化資料區/靜態資料區(Data Segment)
載入的是可執行檔案資料段,儲存於資料段(全域性初始化,靜態初始化資料)的資料的生存週期為整個程式執行過程。
未初始化資料區(BSS)
載入的是可執行檔案BSS段,位置可以分開亦可以緊靠資料段,儲存於資料段的資料(全域性未初始化,靜態未初始化資料)的生存週期為整個程式執行過程。
棧區(stack)
由編譯器自動分配釋放,存放函式的引數值、返回值、區域性變數等。在程式執行過程中實時載入和釋放,因此,區域性變數的生存週期為申請到釋放該段棧空間。
堆區(heap)
用於動態記憶體分配。堆在記憶體中位於BSS區和棧區之間。一般由程式設計師分配和釋放,若程式設計師不釋放,程式結束時有可能由OS回收。
C的變數、函式儲存型別
變數及函式宣告
變數宣告
儲存型別 型別修飾符 資料型別 變數名
函式宣告
儲存型別 返回資料型別 函式名(引數列表)
C變數及函式儲存型別
常見的記憶體錯誤
洩露
定義:通常指堆記憶體洩露。即通過malloc、realloc和new等函式分配記憶體造成的。
錯誤提示:記憶體耗盡
出現原因
堆記憶體分配後,未釋放;
堆記憶體分配後,釋放順序不當;
舉例
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#define ONE_K (1024)
int main() {
char *some_memory;
int size_to_allocate = ONE_K;
int megs_obtained = 0;
int ks_obtained = 0;
while (1) {
for (ks_obtained = 0; ks_obtained < 1024; ks_obtained++)
{
some_memory = (char *)malloc(size_to_allocate);
if (some_memory == NULL) exit(EXIT_FAILURE);
sprintf(some_memory, "Hello World");
}
megs_obtained++;
printf("Now allocated %d Megabytes\n", megs_obtained);
}
exit(EXIT_SUCCESS);
}
記憶體管理的庫函式
記憶體分配
函式原型:void *malloc(size_t size);
標頭檔案:stdlib.h
功能:分配指定長度的記憶體空間
記憶體釋放
函式原型:void free(void *ptr);
標頭檔案:stdlib.h
功能:釋放ptr指標所在的記憶體空間
calloc函式
功能:為一個結構陣列分配記憶體
標頭檔案:stdlib.h
void *calloc(size_t num,size_t elesize)
realloc函式
功能:為一個已經分配的記憶體空間改變長度
標頭檔案:stdlib.h
void realloc(void *exist,size_t new_size)
memcpy函式
功能:將n位元組從src拷貝到dest所指向位置。
extern void *memcpy(void *dest,void *src,n)
memmove函式
功能:帶檢查的拷貝
extern void *memmove(void *dest,void *src,n)
memset函式
功能:初始化指定記憶體單元
extern void *memset(void *s,int c,size_t n)
memchr函式
功能:在一段記憶體空間中查詢某個字元第一次出現的位置。
extern void *memchr(void *s,int c,size_t n)
memcmp函式
功能:字串比較
extern int memcmp(void *s1,void *s2,size_t n)
舉例
#include <stdlib.h>
#define ONE_K (1024)
int main()
{
char *some_memory;
int exit_code = EXIT_FAILURE;
some_memory = (char *)malloc(ONE_K);
if (some_memory != NULL) {
free(some_memory);
exit_code = EXIT_SUCCESS;
}
exit(exit_code);
}