www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 單片機(jī) > C語(yǔ)言與CPP編程
[導(dǎo)讀]1 引言 “緩沖區(qū)溢出”對(duì)現(xiàn)代操作系統(tǒng)與編譯器來(lái)講已經(jīng)不是什么大問(wèn)題,但是作為一個(gè)合格的 C/C++ 程序員,還是完全有必要了解它的整個(gè)細(xì)節(jié)。 計(jì)算機(jī)程序一般都會(huì)使用到一些內(nèi)存,這些內(nèi)存或是程序內(nèi)部使用,或是存放用戶的輸入數(shù)據(jù),這樣的內(nèi)存一般稱作緩沖

1 引言

緩沖區(qū)溢出”對(duì)現(xiàn)代操作系統(tǒng)與編譯器來(lái)講已經(jīng)不是什么大問(wèn)題,但是作為一個(gè)合格的 C/C++ 程序員,還是完全有必要了解它的整個(gè)細(xì)節(jié)。

計(jì)算機(jī)程序一般都會(huì)使用到一些內(nèi)存,這些內(nèi)存或是程序內(nèi)部使用,或是存放用戶的輸入數(shù)據(jù),這樣的內(nèi)存一般稱作緩沖區(qū)。簡(jiǎn)單的說(shuō),緩沖區(qū)就是一塊連續(xù)的計(jì)算機(jī)內(nèi)存區(qū)域,它可以保存相同數(shù)據(jù)類型的多個(gè)實(shí)例,如字符數(shù)組。而緩沖區(qū)溢出則是指當(dāng)計(jì)算機(jī)向緩沖區(qū)內(nèi)填充數(shù)據(jù)位數(shù)時(shí)超過(guò)了緩沖區(qū)本身的容量,溢出的數(shù)據(jù)覆蓋在合法數(shù)據(jù)上。

2 C/C++中內(nèi)存分配

任何一個(gè)源程序通常都包括靜態(tài)的代碼段(或者稱為文本段)和靜態(tài)的數(shù)據(jù)段,為了運(yùn)行程序,操作系統(tǒng)首先負(fù)責(zé)為其創(chuàng)建進(jìn)程,并在進(jìn)程的虛擬地址空間中為其代碼段和數(shù)據(jù)段建立映射。但是只有靜態(tài)的代碼段和數(shù)據(jù)段是不夠的,進(jìn)程在運(yùn)行過(guò)程中還要有其動(dòng)態(tài)環(huán)境。

一般說(shuō)來(lái),默認(rèn)的動(dòng)態(tài)存儲(chǔ)環(huán)境通過(guò)堆棧機(jī)制建立。所有局部變量及所有按值傳遞的函數(shù)參數(shù)都通過(guò)堆棧機(jī)制自動(dòng)分配內(nèi)存空間。如下圖。

程序在內(nèi)存的映射
  • 棧區(qū)(stack):由編譯器自動(dòng)分配與釋放,存放為運(yùn)行時(shí)函數(shù)分配的局部變量、函數(shù)參數(shù)、返回?cái)?shù)據(jù)、返回地址等。其操作類似于數(shù)據(jù)結(jié)構(gòu)中的棧。
  • 堆區(qū)(heap):一般由程序員自動(dòng)分配,如果程序員沒(méi)有釋放,程序結(jié)束時(shí)可能有OS回收。其分配類似于鏈表。
  • 全局區(qū)(靜態(tài)區(qū)static):數(shù)據(jù)段,程序結(jié)束后由系統(tǒng)釋放。全局區(qū)分為已初始化全局區(qū)(data),用來(lái)存放保存全局的和靜態(tài)的已初始化變量和未初始化全局區(qū)(bss),用來(lái)保存全局的和靜態(tài)的未初始化變量。
  • 常量區(qū)(文字常量區(qū)):數(shù)據(jù)段,存放常量字符串,程序結(jié)束后有系統(tǒng)釋放。
  • 代碼區(qū):存放函數(shù)體(類成員函數(shù)和全局區(qū))的二進(jìn)制代碼,這個(gè)段在內(nèi)存中一般被標(biāo)記為只讀,任何對(duì)該區(qū)的寫(xiě)操作都會(huì)導(dǎo)致段錯(cuò)誤(Segmentation Fault)。

需要特別注意的是,堆(Heap)和棧(Stack)是有區(qū)別的,很多程序員混淆堆棧的概念,或者認(rèn)為它們就是一個(gè)概念。簡(jiǎn)單來(lái)說(shuō),它們之間的主要區(qū)別可以表現(xiàn)在如下五個(gè)方面。

分配和管理方式不同

堆是動(dòng)態(tài)分配的,其空間的分配和釋放都由程序員控制。也就是說(shuō),堆的大小并不固定,可動(dòng)態(tài)擴(kuò)張或縮減,其分配由malloc()等這類實(shí)時(shí)內(nèi)存分配函數(shù)來(lái)實(shí)現(xiàn)。當(dāng)進(jìn)程調(diào)用malloc等函數(shù)分配內(nèi)存時(shí),新分配的內(nèi)存就被動(dòng)態(tài)添加到堆上(堆被擴(kuò)張);當(dāng)利用free等函數(shù)釋放內(nèi)存時(shí),被釋放的內(nèi)存從堆中被剔除(堆被縮減)。

而棧由編譯器自動(dòng)管理,其分配方式有兩種:靜態(tài)分配和動(dòng)態(tài)分配。靜態(tài)分配由編譯器完成,比如局部變量的分配。動(dòng)態(tài)分配由alloca()函數(shù)進(jìn)行分配,但是棧的動(dòng)態(tài)分配和堆是不同的,它的動(dòng)態(tài)分配是由編譯器進(jìn)行釋放,無(wú)需手工控制。

申請(qǐng)的大小限制不同

棧是向低地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是一塊連續(xù)的內(nèi)存區(qū)域,棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預(yù)先規(guī)定好的,能從棧獲得的空間較小。

堆是向高地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域,這是由于系統(tǒng)是由鏈表在存儲(chǔ)空閑內(nèi)存地址,自然堆就是不連續(xù)的內(nèi)存區(qū)域,且鏈表的遍歷也是從低地址向高地址遍歷的,堆的大小受限于計(jì)算機(jī)系統(tǒng)的有效虛擬內(nèi)存空間,

由此空間,堆獲得的空間比較靈活,也比較大。在 32 位平臺(tái)下,VC6 下默認(rèn)為 1M,堆最大可以到 4G;

申請(qǐng)效率不同

  • 棧由系統(tǒng)自動(dòng)分配,速度快,但是程序員無(wú)法控制。
  • 堆是有程序員自己分配,速度較慢,容易產(chǎn)生碎片,不過(guò)用起來(lái)方便。

產(chǎn)生碎片不同

對(duì)堆來(lái)說(shuō),頻繁執(zhí)行malloc或free勢(shì)必會(huì)造成內(nèi)存空間的不連續(xù),形成大量的碎片,使程序效率降低;而對(duì)棧而言,則不存在碎片問(wèn)題。

內(nèi)存地址增長(zhǎng)的方向不同

  • 堆是向著內(nèi)存地址增加的方向增長(zhǎng)的,從內(nèi)存的低地址向高地址方向增長(zhǎng);
  • 棧的增長(zhǎng)方向與之相反,是向著內(nèi)存地址減小的方向增長(zhǎng),由內(nèi)存的高地址向低地址方向增長(zhǎng)。

假設(shè)一個(gè)程序的函數(shù)調(diào)用順序?yàn)椋褐骱瘮?shù)main調(diào)用函數(shù)func1,函數(shù)func1調(diào)用函數(shù)func2。當(dāng)這個(gè)程序被操作系統(tǒng)調(diào)入內(nèi)存運(yùn)行時(shí),其對(duì)應(yīng)的進(jìn)程在內(nèi)存中的映射結(jié)果如下圖所示

例子中的內(nèi)存映射

進(jìn)程的棧是由多個(gè)棧幀構(gòu)成的,其中每個(gè)棧幀都對(duì)應(yīng)一個(gè)函數(shù)調(diào)用。當(dāng)調(diào)用函數(shù)時(shí),新的棧幀被壓入棧;當(dāng)函數(shù)返回時(shí),相應(yīng)的棧幀從棧中彈出。由于需要將函數(shù)返回地址這樣的重要數(shù)據(jù)保存在程序員可見(jiàn)的堆棧中,因此也給系統(tǒng)安全帶來(lái)了極大的隱患。

當(dāng)程序?qū)懭氤^(guò)緩沖區(qū)的邊界時(shí),就會(huì)產(chǎn)生所謂的“緩沖區(qū)溢出”。發(fā)生緩沖區(qū)溢出時(shí),就會(huì)覆蓋下一個(gè)相鄰的內(nèi)存塊,導(dǎo)致程序發(fā)生一些不可預(yù)料的結(jié)果:也許程序可以繼續(xù),也許程序的執(zhí)行出現(xiàn)奇怪現(xiàn)象,也許程序完全失敗或者崩潰等。

緩沖區(qū)溢出

對(duì)于緩沖區(qū)溢出,一般可以分為4種類型,即棧溢出、堆溢出、BSS溢出與格式化串溢出。其中,棧溢出是最簡(jiǎn)單,也是最為常見(jiàn)的一種溢出方式。

沒(méi)有保證足夠的存儲(chǔ)空間存儲(chǔ)復(fù)制過(guò)來(lái)的數(shù)據(jù)

void function(char *str) 
{
   char buffer[10];
   strcpy(buffer,str);
}

上面的strcpy()將直接把str中的內(nèi)容copybuffer中。這樣只要str的長(zhǎng)度大于 10 ,就會(huì)造成buffer的溢出,使程序運(yùn)行出錯(cuò)。存在象strcpy這樣的問(wèn)題的標(biāo)準(zhǔn)函數(shù)還有strcat(),sprintf(),vsprintf(),gets(),scanf()等。對(duì)應(yīng)的有更加安全的函數(shù),即在函數(shù)名后加上_s,如scanf_s()函數(shù)。

  • 嚴(yán)格檢查輸入長(zhǎng)度和緩沖區(qū)長(zhǎng)度。
  • 常見(jiàn)的高危函數(shù)
函數(shù) 嚴(yán)重性 防范手段
gets() 最危險(xiǎn) 使用 fgets(buf, size, stdin)
strcpy() 很危險(xiǎn) 改為使用 strncpy()
strcat() 很危險(xiǎn) 改為使用 strncat()
sprintf() 很危險(xiǎn) 改為使用snprintf(),或者使用精度說(shuō)明符
scanf() 很危險(xiǎn) 使用精度說(shuō)明符,或自己進(jìn)行解析
sscanf() 很危險(xiǎn) 使用精度說(shuō)明符,或自己進(jìn)行解析
fscanf() 很危險(xiǎn) 使用精度說(shuō)明符,或自己進(jìn)行解析
vfscanf() 很危險(xiǎn) 使用精度說(shuō)明符,或自己進(jìn)行解析
vfscanf() 很危險(xiǎn) 改為使用 vsnprintf(),或者使用精度說(shuō)明符
vscanf() 很危險(xiǎn) 使用精度說(shuō)明符,或自己進(jìn)行解析
vsscanf() 很危險(xiǎn) 使用精度說(shuō)明符,或自己進(jìn)行解析
streadd() 很危險(xiǎn) 使用精度說(shuō)明符,或自己進(jìn)行解析

整數(shù)溢出

  1. 寬度溢出:把一個(gè)寬度較大的操作數(shù)賦給寬度較小的操作數(shù),就有可能發(fā)生數(shù)據(jù)截?cái)嗷蚍?hào)位丟失
#include<stdio.h>

int main()
{
  signed int value1 = 10;
  usigned int value2 = (unsigned int)value1;
}
  1. 算術(shù)溢出,該程序即使在接受用戶輸入的時(shí)候?qū)、b的賦值做安全性檢查,a+b 依舊可能溢出:
#include<stdio.h>

int main()
{
  int a;
  int b;
  int c=a*b;
  return 0;
}

數(shù)組索引不在合法范圍內(nèi)

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;
}

其中:posint類型,可能為負(fù)數(shù),這會(huì)導(dǎo)致在數(shù)組所引用的內(nèi)存邊界之外進(jìn)行寫(xiě)入,可以將pos類型改為size_t避免

空字符錯(cuò)誤

例如:

//錯(cuò)誤
char array[]={'0','1','2','3','4','5','6','7','8'};
//正確的寫(xiě)法應(yīng)為:
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’};


點(diǎn)【在看】是最大的支持 

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢(shì)抑制與過(guò)流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問(wèn)題卻十分常見(jiàn),不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問(wèn)題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車場(chǎng)照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢(shì)逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問(wèn)題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來(lái)解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開(kāi)關(guān)電源具有效率高的特性,而且開(kāi)關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開(kāi)關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉