C語言的汙垢,一個能汙染記憶體的神祕操作!神級坑位再現~
本文目的是為了更好的理解指標和記憶體管理
背景
我們定義一個變數A,修改另外一個一個變數B,導致A的值被修改,我們稱它為記憶體汙染。
案例
如下程式,正常的預期輸出應該是:97 98 256,但正確的結果卻是1 0 256,意不意外,驚不驚喜
這時候主要問題發生在int *ptr = (int *)&b;這裡,對&b強型別轉換,汙染了a的記憶體
a的地址比b地址大(堆從低到高, 棧從高到低分配地址)
————————————
#include <stdio.h> int main(void) { char a = 'a', b = 'b';int *ptr = (int *)&b; *ptr = 256; printf("%d,%d,%d \n", a, b, *ptr); // 1 0 256 return 0; }
驗證
我們通過gdb除錯,打印出各個變數的地址
————————————
$ gdb a.out (gdb) b 7 Breakpoint 1 at 0x100000f47: file test.c, line 7. (gdb) b 11 Breakpoint 2 at 0x100000f77: file test.c, line 11. Thread 2 hit Breakpoint 1, main () at test.c:7 7 int *ptr = (int *)&b; (gdb) x/1tb &a 0x7ffeefbff55b: 01100001 (gdb) x/1tb &b 0x7ffeefbff55a: 01100010 (gdb) n 8 *ptr = 256; (gdb) n 10 printf("%d,%d,%d \n", a, b, *ptr); // 1 0 256 (gdb) n 1,0,256 Thread 2 hit Breakpoint 2, main () at test.c:1111 return 0; (gdb) x/1tb &a 0x7ffeefbff55b: 00000001 (gdb) x/1tb &b 0x7ffeefbff55a: 00000000 (gdb) x/4tb ptr 0x7ffeefbff55a: 00000000 00000001 00000000 00000000
————————————
我們在*ptr = 256;這裡打了斷點,然後分別看執行前後a,b的變化
我們先在斷點前,使用gdb命令x/1tb &a檢視記憶體
✪ a的地址0x7ffeefbff55b值為十進位制97
✪ b的地址0x7ffeefbff55a值為十進位制98
結論:a的地址比b的地址高
(gdb) x/1tb &a
0x7ffeefbff55b: 01100001
(gdb) x/1tb &b
0x7ffeefbff55a: 01100010
————————————
然後我們執行*ptr = 256;這句後,再次檢視:
(gdb) x/1tb &a
0x7ffeefbff55b: 00000001
(gdb) x/1tb &b
0x7ffeefbff55a: 00000000
(gdb) x/4tb ptr
0x7ffeefbff55a: 00000000 00000001 00000000 00000000
————————————
ptr賦值245後,記憶體中值為:00000000 00000001 00000000 00000000
直接汙染了a的記憶體,把a值修改為了00000001因為ptr為int*型別,佔用4個位元組,a的地址比ptr高1,屬於4個位元組之內,所以被汙染了。
是不是很神奇呢,下次遇到這種坑小夥伴一定要注意哦!
————————————
看到這裡你是不是對C語言又有了一點新的認知呢~
如果你喜歡這篇文章的話,動動小指,點個贊再走~
如果你想學程式設計,小編推薦一個C語言/C++程式設計學習基地【點選進入】!
一個活躍、高逼格、高層次的程式設計學習殿堂;程式設計入門只是順帶,思維的提高才有價值!
涉及:程式設計入門、遊戲程式設計、網路程式設計、Windows程式設計、Linux程式設計、Qt介面開發、黑客等等....