記憶體訪問越界問題

2022-04-05 18:20:41 字數 1697 閱讀 5187

**

1. 原理分析

經常有些新c++程式設計師問:c++的類的成員個數是不是有限制,為什麼我加乙個變數後程式就死了?或者說:是不是成員變數的順序很重要,為什麼我兩個成員變數順序換一換程式就不行了?凡此種種之怪現象,往往都是記憶體訪問越界所致。

何謂記憶體訪問越界,簡單的說,你向系統申請了一塊記憶體,在使用這塊記憶體的時候,超出了你申請的範圍。例如,你明明申請的是100位元組的空間,但是你由於某種原因寫入了120位元組,這就是記憶體訪問越界。記憶體訪問越界的後果是:你的寫入破壞了本不屬於你的空間。

下面是乙個簡單的例子:

int a;

char b[16]="abcd";

int c;

a = 1;

c = 2;

printf("a=%d,c=%d\n", a,c);

memset(b, 0,32); //注意這裡訪問越界了,你只有16位元組空間,卻修改了32位元組

printf("a=%d,c=%d\n", a,c);

你可以看出,在memset前後,兩個printf語句列印出來的值並不一樣,因為memset越界後修改了a或者c的值(由於不同編譯器對變數在空間中順序的安排可能有不同策略,因此我用兩個變數,希望能抓到越界資訊。對於vc,debug模式下系統新增了很多填充位元組,你可能需要增加越界的數量才能看到效果)

2. 為什麼增加乙個變數後程式就崩潰了?

增加乙個變數後,記憶體中變數的布局也發生了變化。如果乙個記憶體越界破壞了乙個不含指標的結構,程式雖然邏輯不對,但是不至於崩潰。但是如果增加變數後,記憶體訪問越界破壞了乙個指標,則會導致程式崩潰。

例如:int a;

char b[128];

//bool c;

char* d=new char[128];

int e;

b[136] = '\0';

b[137] = '\0';

b[138] = '\0';

b[139] = '\0';

strcpy(d, "haha");

注意, b訪問越界了8個位元組位置處的4個位元組。如果沒有c,那麼越界破壞了e變數,不會導致程式崩潰。但是加上c之後,破壞的變數可能就是d了,由於指標被破壞後,一旦訪問就是記憶體訪問違例,導致程式崩潰。

這也解釋了為什麼交換順序會導致程式崩潰。如果上面情況沒有變數c,你交換e和d,結構也是類似的,程式也一樣要崩潰。

3. 為什麼有些情況越界了程式也沒錯?

這主要是說這個話的人對什麼是「錯」沒有正確的認識。程式不是只有崩潰了才是錯!你破壞了別的變數,那個變數總有被使用的時候,儘管那個變數不會導致諸如程式崩潰、報警之類的嚴重錯誤,但是其計算結果必然是錯誤的。你說「程式沒錯」,是因為你根本沒有發現錯誤而已。這種情況甚至比程式直接崩潰還要惡劣,因為程式一旦崩潰你肯定會去查,可以在導致真正嚴重的問題之前就把問題解決了。而如果計算錯誤隱藏到很晚,你的損失就可能很大了。(例如,一顆衛星上天了,你才發現一台儀器由於軟體故障無法測量真正的資料,那得多少損失?)

4. 如何解決記憶體訪問越界問題?

老實說沒有好的方法。遇到這種問題,首先你得找到**有記憶體訪問越界,而乙個比較麻煩得問題在於,出現錯誤得地方往往不是真正記憶體越界得地方。對於記憶體訪問越界,往往需要進行仔細得**走查、單步跟蹤並觀察變數以及在除錯環境得幫助下對變數進行寫入跟蹤(如vc6就有一旦變數被修改就break得機制)。

更重要得是,程式設計師要養成良好的程式設計習慣,在修改每個陣列時一定要對這個陣列有多少空間有清醒的認識,否則一旦出錯,找到原因是很痛苦的事情。

記憶體訪問越界

1.記憶體越界分配的原理 何謂記憶體訪問越界,簡單的說,你向系統申請了一塊記憶體,在使用這塊記憶體的時候,超出了你申請的範圍。例如,你明明申請的是100位元組的空間,但是你由於某種原因寫入了120位元組,這就是記憶體訪問越界。記憶體訪問越界的後果是 你的寫入破壞了本不屬於你的空間。如下所示的 輸出 ...

關於C 記憶體越界訪問的問題

今天是第一天寫部落格,哈哈,想想還有點激動,啦啦。言歸正傳啊,今天主要是說c基礎裡的strcat函式,它的意思主要是進行字元的拼接,例如 來自 函式名 strcat 功 能 字串拼接函式 用 法 char strcat char destin,char source 程式例 i nclude i n...

mysql 記憶體越界 strncpy越界

strncpy dest,src,n 似乎是安全的函式 原型 char strncpy char restrict s1,const char restrict s2,size t n 今天碰到了問題,是由於對strncpy理解不夠造成的 man裡 事實上s2往往不如n那麼長,於是s1剩餘部分會全填...