![](http://static.javashuo.com/static/loading.gif)
1 引言
2 C/C++中內存分配
![](http://static.javashuo.com/static/loading.gif)
-
棧區(stack):由編譯器自動分配與釋放,存放爲運行時函數分配的局部變量、函數參數、返回數據、返回地址等。其操做相似於數據結構中的棧。 -
堆區(heap):通常由程序員自動分配,若是程序員沒有釋放,程序結束時可能有OS回收。其分配相似於鏈表。 -
全局區(靜態區static):數據段,程序結束後由系統釋放。全局區分爲已初始化全局區(data),用來存放保存全局的和靜態的已初始化變量和未初始化全局區(bss),用來保存全局的和靜態的未初始化變量。 -
常量區(文字常量區):數據段,存放常量字符串,程序結束後有系統釋放。 -
代碼區:存放函數體(類成員函數和全局區)的二進制代碼,這個段在內存中通常被標記爲只讀,任何對該區的寫操做都會致使段錯誤(Segmentation Fault)。
分配和管理方式不一樣
malloc()
等這類實時內存分配函數來實現。當進程調用
malloc
等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張);當利用
free
等函數釋放內存時,被釋放的內存從堆中被剔除(堆被縮減)。
alloca()
函數進行分配,可是棧的動態分配和堆是不一樣的,它的動態分配是由編譯器進行釋放,無需手工控制。
申請的大小限制不一樣
申請效率不一樣
-
棧由系統自動分配,速度快,可是程序員沒法控制。 -
堆是有程序員本身分配,速度較慢,容易產生碎片,不過用起來方便。
產生碎片不一樣
內存地址增加的方向不一樣
-
堆是向着內存地址增長的方向增加的,從內存的低地址向高地址方向增加; -
棧的增加方向與之相反,是向着內存地址減少的方向增加,由內存的高地址向低地址方向增加。
main
調用函數
func1
,函數
func1
調用函數
func2
。當這個程序被操做系統調入內存運行時,其對應的進程在內存中的映射結果以下圖所示
![](http://static.javashuo.com/static/loading.gif)
「緩衝區溢出」
。發生緩衝區溢出時,就會覆蓋下一個相鄰的內存塊,致使程序發生一些不可預料的結果:也許程序能夠繼續,也許程序的執行出現奇怪現象,也許程序徹底失敗或者崩潰等。
緩衝區溢出
沒有保證足夠的存儲空間存儲複製過來的數據
void function(char *str)
{
char buffer[10];
strcpy(buffer,str);
}
strcpy()
將直接把
str
中的內容
copy
到
buffer
中。這樣只要
str
的長度大於 10 ,就會形成
buffer
的溢出,使程序運行出錯。存在象
strcpy
這樣的問題的標準函數還有
strcat(),sprintf(),vsprintf(),gets(),scanf()
等。對應的有更加安全的函數,即在函數名後加上
_s
,如
scanf_s()
函數。
-
嚴格檢查輸入長度和緩衝區長度。 -
常見的高危函數
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
整數溢出
-
寬度溢出:把一個寬度較大的操做數賦給寬度較小的操做數,就有可能發生數據截斷或符號位丟失
#include<stdio.h>
int main()
{
signed int value1 = 10;
usigned int value2 = (unsigned int)value1;
}
-
算術溢出,該程序即便在接受用戶輸入的時候對a、b的賦值作安全性檢查,a+b 依舊可能溢出:
#include<stdio.h>
int main()
{
int a;
int b;
int c=a*b;
return 0;
}
數組索引不在合法範圍內
enum {TABLESIZE = 100};
int *table = NULL;
int insert_in_table(int pos, int value) {
if(!table) {
table = (int *)malloc(sizeof(int) *TABLESIZE);
}
if(pos >= TABLESIZE) {
return -1;
}
table[pos] = value;
return 0;
}
pos
爲
int
類型,可能爲負數,這會致使在數組所引用的內存邊界以外進行寫入,能夠將
pos
類型改成
size_
t避免
空字符錯誤
//錯誤
char array[]={'0','1','2','3','4','5','6','7','8'};
//正確的寫法應爲:
char array[]={'0','1','2','3','4','5','6','7','8',’\0’};
//或者
char array[11]={'0','1','2','3','4','5','6','7','8','9’};
![](http://static.javashuo.com/static/loading.gif)
本文分享自微信公衆號 - C語言入門到精通(c_printf)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。程序員