您好,登錄后才能下訂單哦!
這篇文章主要講解了“C/C++自主分配出現double free or corruption問題如何解決”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“C/C++自主分配出現double free or corruption問題如何解決”吧!
C 語言提供了兩個函數用于分配和釋放內存 malloc 和 free,需要引用頭文件 <stdlib.h>。<stdlib.h> 是 C 標準庫頭文件 為 C 語言程序員提供可靠、高效的函數,以實現動態內存分配、數據類型轉換、偽隨機數生成、過程控制、搜索和排序、數學以及多字節或寬字符函數,還包括一些常用常數,目的是促進組織和平臺間的代碼標準化。
#include <stdlib.h> #include <stdio.h> int main() { int *ptr = malloc(sizeof(int)); *ptr = 100; printf("%d", *ptr); free(ptr); return 0; }
輸出:
100
調用 malloc 會分配一塊內存空間,并將這塊內存空間的首地址返回。調用時,需要傳入目標內存空間的大小,單位按照字節(Byte)算,而返回的地址數據類型是 void*,所以,根據目標空間的具體用途轉換即可。
這塊內存空間在分配之后還屬于未初始化的狀態,如果對內存空間的使用比較復雜,建議先用 memset 初始化一下。
內存空間使用完,需要使用 free 釋放掉,避免閑置浪費,否則就算是內存泄漏了。內存泄露會直到程序進程結束為止。
在其它的高級語言里,比如 Java、Python 等,出于內存安全的考慮,都不會允許用戶自己管理內存,而 C++ 是個例外,這可能來自于 C 語言的傳承。
C++ 里同樣提供了 malloc 和 free,但是引用的頭文件變成了 <cstdlib>。<cstdlib>是 <stdlib.h> 增強版,而且所有內容都在命名空間內聲明,所以使用前必須通過命名空間引用。
另外 C++ 還提供了兩個額外的操作符用于分配和釋放內存,分別是 new 和 delete。
#include <iostream> using namespace std; int main() { int *ptr = new int; *ptr = 100; cout << *ptr << endl; delete ptr; return 0; }
輸出:
100
關鍵詞 new 后接上一個數據類型,然后分配和數據類型 int 對應大小的內存空間,并返回首地址。對應地,new 申請的內存空間被使用完不再需要時,應該使用關鍵詞 delete 釋放,delete 直接操作內存空間首地址。
借來的錢用得可以很爽,是的,常人都這樣。不過,每到要還錢的時候就特別不情愿,要么推三推四,要么直接抵賴,一不留神就忘了是否有還過這事。
比如,張三本來一直在外租房將就著過日子,隨著家里人口逐漸增多,就和老婆合計著從銀行貸了一筆資金準備買房嘛,貸了款之后,銀行貸款經理就告訴他,“張先生,你們家以后每月就得由一名代表人來還貸款,不需要幾個人同時還的,記住了哈!”
好了,這個故事給了我們什么啟發呢?就是資金或者資源的借入借出需要有一個管理人,這樣可以避免混亂進而出錯。
同樣的,在 C/C++ 的編程里邊,經常會出現一些內存資源管理混亂而出現的報錯甚至運行時崩潰的問題,比如 double free or corruption。
#include <iostream> using namespace std; int main() { int *ptr = new int; *ptr = 100; cout << *ptr << endl; delete ptr; delete ptr; return 0; }
執行
100 free(): double free detected in tcache 2 Aborted (core dumped)
程序執行崩潰并報錯 double free,根本原因是對同一內存地址調用了多次的 free 或 delete 執行釋放,這會導致應用的內存管理數據結構被損壞,甚至會允許惡意用戶在內存任意區域寫入數據。這類損壞會導致程序崩潰或者程序的部分執行流程被改變。如果攻擊者這個時候特意覆蓋特定的寄存器或者內存區域來引導執行他們的代碼,進而可以產生提升權限的交互式 shell,這樣就完全被破防了。
這也算是內存泄漏的一種,系統一旦檢測到 double free 也會終止進程繼續執行(Aborted)。
一塊內存被釋放之后,空閑的內存會被放入鏈表中,用于重新管理和組合不同的空閑內存碎片,便于將來用于分配更大的內存空間。這個鏈表屬于雙向鏈表,每個空閑的內存空間都可以往前和往后查找其它內存空間。
那么攻擊者可以利用這個過程嗎?
答案是肯定的。當 free 被調用時,攻擊者可以讓原本需要被鏈表管理的空閑內存取消鏈接,覆蓋寄存器值并從緩沖區載入shell代碼,最終往內存寫入任意值。
上面的示例代碼簡單演示了 double free 的觸發,平常出現這種報錯的條件并不比上面的情形要復雜多少。比如,釋放同一塊內存的動作在相隔了幾百甚至更多行的位置執行,有的還發生在不同源碼文件,這就會讓程序員容易多次釋放。下面嘗試總結一下,來看一下常見的犯錯情形:
釋放前判斷的條件錯誤或者其它不常見的情況
內存被釋放后還在使用
內存釋放的管理責任方混亂
其實,細看一下上面總結的幾種常見犯錯情形,我們也可以很好地避免低級錯誤。
有個最佳實踐是,分配的內存地址存儲變量 ptr 在定義聲明時就應該初始化為 NULL,內存被釋放后應立刻將 ptr 置為 NULL,使用這塊內存或者釋放前應該遵循先判斷內存空間是否有效的原則,簡單點可以用 (ptr != NULL)。
另外,負責釋放的管理責任方應該盡量單一,即使橫跨多個源文件或模塊。這里有個道理就是避免”多龍治水“。
中國在過去一直是個農業大國,有著重農輕商的歷史,各種典故都有著農業的影子。
相傳,幾龍治水、幾牛耕地那是對當年農業收成的預示,不妨翻一下老黃歷看看?“龍”是管雨的神,以五龍治水可獲風調雨順,因東南西北中都有神龍,各施其職。龍少了當年就要發大水;龍多了當年將要天大旱。原因是管雨的龍神少了怕管不過來,就忙忙碌碌四處播雨以至大澇;管雨的龍神多了呢,就像“三個和尚無水吃”一樣以至大旱。至于澇到什么程度還看治水的龍少到什么程度,龍越少澇得越嚴重。旱的程度亦一樣。
因此就有了“龍多不下雨”的諺語。
計算機編程說到底還是程序員的思維體現,人情世故也會反映在代碼的邏輯上。
感謝各位的閱讀,以上就是“C/C++自主分配出現double free or corruption問題如何解決”的內容了,經過本文的學習后,相信大家對C/C++自主分配出現double free or corruption問題如何解決這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。