面試|搬了這麼久的磚,居然還不知道什麼“踩記憶體”
摘要:你是否在總是聽到“記憶體越界”,“指標指向了非法地址”等常見問題呢?但是在面試過程中總有一些學術嚴謹(裝13)的面試官給這一類問題取個名字-踩記憶體。如果你沒聽過,是不是就顯得沒品味(正常)。簡而言之,踩記憶體就指訪問了不應該訪問的記憶體地址。
關於踩記憶體
踩記憶體就是訪問了不應該訪問的記憶體,常見有幾種:
1、越界踩;
越界踩的意思就是踩壞的記憶體就在你分配記憶體的旁邊,也就是在界限附近,出現這種情況一般是由於申請的記憶體小了。舉個例子:
char *p;
p = malloc(5);strcpy(p, “hello”);
strcpy複製了6個位元組(字串“hello”有6個位元組,包括最後的‘\0’),但是指標p指向所分配的記憶體只有5個位元組,所以就越界了。
當然還有一種情況就是陣列越界,這也是新手時常發生的,這也屬於一種越界踩,除此之外,越界踩還有一種比較難發現的情況,就是棧溢位的情況,我們知道棧記憶體一般都是有固定大小的,如果一個函數里面變數過多大就會導致棧溢位,出現越界踩。舉個例子:
int func(){
char tmp[1024000000000];
for(int i = 0;i < 1024000000;i++){
tmp=‘H’;
}
}
2、use after free;
這種情況是由於指標在使用的之前又被釋放掉,那麼這塊記憶體很有可能又被分配出去了。這個理解起來就比較簡單:
char *p;
p = malloc(6);strcpy(p, “hello”);free(p); // p記憶體被回收了strcpy(p, “world”); /* p記憶體很可能再次被分配出去,這條語句直接把屬於你的記憶體踩壞 */
3、隨機踩;
如果出現隨機踩的話,那麼問題排查起來就比較頭痛了,因為不知道是在程式的哪個位置出現問題,因為有可能每次出現問題的地方都不一樣,下面簡單列舉一個例子:
int func(int i){
char tmp[10];
tmp=‘H’;
}
這種情況下變數i沒有做範圍檢查有可能是負數有可能很大,所以每次踩壞的地方都不一樣,還有一種情況即就是沒有初始化。
總結
當面試過程中被問到“踩記憶體”改該如何回答呢?
我遇到過踩記憶體的,踩記憶體就是訪問了不應該訪問的記憶體地址,比如過說陣列或記憶體越界啊,指標未初始化啊或使用的時候已經被釋放掉啊等都會造成踩記憶體的現象。
那麼我們為了避免出現這種低階bug,需要養成:
1。入參一定要做邊界檢查,防止溢位
2。 程式碼不要巢狀太深,在多執行緒多通道的場景下,很容易重複釋放/申請資源
3。 不要定義過多的區域性變數,陣列,防止棧溢位,核心中棧的大小是8k吧。看情況使用kmalloc
4。 釋放了的資源及時置空,如果不是立馬就return的話。分支比較多的程式碼,很容易就~~~
Q:出現了踩記憶體應該如何排查?
A:透過gdb進行除錯定位出問題的程式碼,如果是隨機踩的情況,可以藉助valgrind工具進行排查。
公眾號:【PisCO菜鳥成長】