1 局部優先法則 只要局部變量定義,就會屏蔽全局變量。
內存管理
1.1 內存區域的劃分
代碼區 只讀常量區 全局區/數據區 BSS段 堆區 棧區
8048444 80486c0 804a 804a 808f bfa1e
總結
1 按照地址從小到大的排列 進程中的內存區域依次是:代碼區 只讀常量區 全局區/數據區 BSS段 堆區 棧區。
2 其中代碼區和只讀常量區統稱為代碼區,全局區數據區和BSS段,統稱為全局區或者數據區。在
3 在進程的內存區域的最上面,用來存放命令行參數和環境變量。堆區和棧區沒有明顯的分割線。可以進行微調,並且堆區的分配一般按照地址從小到大進行,而棧區的分配一般按照從大到小進行分配。
1.2 字符串的存儲形式之間的比較
指針變量的指向可以改變,但是數組名的指向不可以改變。
指針變量指向的字符串內容不可以改變,數組存儲的內容可以改變。因為 :不可以修改只讀常量區的內容。
對於存放常量字符串的堆區來說,指針的指向和指針指向的內容都可以改變。
1.3 虛擬內存管理技術
unix/linux 系統的內存都是采用虛擬內存管理技術進行管理,每個進程都有0-4G的內存地址,(虛擬的不是真的存在的),由操作系統負責吧虛擬內存地址和真是的物理地址映射取來,因此,不同的進程中虛擬地址空間看起來是相同的,但是對應的物理內存是不同的。
其中0-3G的虛擬空間叫做用戶空間,其中3-4G空間之間的虛擬地址空間叫做內核空間,用戶程序一般運行在用戶空間,內核空間只有系統內核才能訪問,用戶程序不能直接訪問內核空間,但是系統內核提供一些系統函數負責將程序從用戶空間切換到內核空間執行,執行完畢後再切換回到用戶空間。
內存地址的基本單位是字節,內存映射的基本單位是內存頁,目前主流的操作系統的內存頁大小是4KB(4096字節)。
1.4 段錯誤的由來
1 scanf 函數的使用,沒加取地址符號
2 指針的使用之中 int *pi;野指針 int *pi =NULL; 空指針。
再用scanf 也會引發段錯誤。
3 使用未映射的虛擬地址
4 對沒有操作權限的內存進行操作
例如 對只讀常量區進行寫操作,可能引發段錯誤。
1.5 使用malloc 函數申請動態內存
1 使用malloc 申請動態內存的注意事項。
使用malloc 函數申請內存時候,除了申請的多需要的內存大小之外,可能還會申請額外的12 個字節,用來存儲一些管理內存相關的信息,比如內存的大小等等。
2 使用malloc 申請內存,不能對所申請的內存空間進行越界訪問,避免造成數據結構的破壞
3#include
getpid(); 獲取當前進程的進程號。
cat 查看內容 /proc/進程號/maps 用來查看指定內存的分配情況
使用malloc 申請原則
一般來說,使用這個函數申請比較小的動態內存時候,操作系統會一次性分配33個內存頁的大小,最終的目的就是為了提高效率,
利用 size a.out查看a.out 的內存分配。
1.6 使用free 函數釋放動態內存
十六進制的1000就是一個內存頁,一般來說使用malloc 來分配比較大的內存時候,系統會分配34個內存頁,當所申請的內存超過34時候,系統會再次分配33個內存頁,也就是按照33 個內存頁為基本單位
而使用free 來釋放內存時候,則釋放多少就減少多少,當使用free 釋放完畢所有的內存時候,系統可能保留33個內存頁來方便再次申請使用,提高效率。
1.7 內存管理的相關函數
1 getpagesize 函數
函數功能
主要用來獲取當前內存頁的大小,一般來說是4kb;
2 sbrk 函數
功能:#include
void *sbrk (intptr_t increment);
函數功能 主要是用來調整動態內存的大小,可增加和減少。參數可以是整數和負數。
increment 如果大於0;表示申請內存空間,參數increment<0;表示釋放內存,如果=0;表示獲取當前內存空間的當前位置。
返回值 如果成功返回調整內存大小之前的位置,失敗返回 (void* )-1;
一般使用sbrk 申請比較小的內存,系統默認分配一個內存頁大小,一旦申請的內存頁超過一個內存頁的時候,再次分配一個內存頁,也就是按照一個內存頁為基本單位進行分配,而釋放內存時候,如果釋放之後剩下的內存足夠用一個內存頁表示,則一次性釋放一個內存頁。
使用sbrk 申請內存不會申請額外的內存空間來管理相關信息
使用sbrk 函數申請內存比釋放內存方便
3 brk 函數
功能 : int brk(void *addr);
函數功能: 主要用於根據參數指定的目標位置調整內存的大小,
目標位置和之前目標位置相比,來確定是分配還是回收內存。
需要先獲取當前位置來作為基准位置,
使用brk 函數釋放內存比較方便,因此一般都使用sbrk 和brk 函數配合使用。
使用sbrk 函數申請內存,使用brk 函數釋放內存,首先申請一個int 類型的大小空間,存放100;再申請一個double 類型空間放3.14。最後申請一個長度是10 個字節的字符空間,存放hellow ,要求打印上述三個變量,釋放內存。