malloc为什么会报错:memory corruption
最近遇到一個問題,很有意思,在此記錄下,以備后續參考。
程序運行異常,報錯:malloc: memory corruption.
用gdb?調試程序,bt?如下,程序在申請344 bytes內存時失敗。
疑問:344bytes內存并不大,為何會失敗呢?
進一步,打開AddressSanitizer,重選編譯并運行程序,AddressSanitizer報錯如下,報錯內容分3部分貼出如下(信息安全,隱藏掉部分堆棧信息):
1.?重點:紅色字體:heap-buffer-overflow on address 0xf3805ef0, 藍色字體, WRITE?of size 4 at 0xf3805ef0
解釋:堆溢出,在*.c的211行對0xf3805ef0地址非法寫,嘗試寫4個byte.
2.綠色字體:0xf3805ef0 is located 192 byte to the right of 688-byte regin?[0xf3805b80,0xf3805e30)
?在*.c的507行分配了688個byte -?對應內存區域[0xf3805b80,0xf3805e30),?程序非法訪問的地址0xf3805ef0 位于此內存區域右側的192個byte的位置。
3. Summary.
分析過程不必贅述,我把結論寫一下:
1.? 在*.c的507行分配了688個byte -?對應內存區域[0xf3805b80,0xf3805e30)
? ? 分析code,?發現這里是分配了2個結構體struct M,sizeof(struct M) = 344.? ??
typedef struct M
{...int data;...
} M_t
2.? 在*.c的211行對0xf3805ef0地址非法寫,嘗試寫4個byte.
? ?查看code,在211行嘗試寫一個struct M的成員data, 而data成員之前結構體成員的長度為192.
?
注意cellGroupId的offset 和 size.
?
回味下面ASAN的提示:
0xf3805ef0 is located 192 byte to the right of 688-byte regin?[0xf3805b80,0xf3805e30)
由此可以推測:程序動態分配了2個struct M,?由于code?存在bug,?卻訪問了第三個struct M.?
最后進一步debug,發現程序確實是指針操作出錯,訪問了2個struct M后面的內存。
思考:malloc失敗 與 AddressSanitizer: heap-buffer-overflow
沒有開啟AddressSanitizer時,程序寫struct M的成員data時并沒有直接報錯,而是延遲到再次malloc內存時報錯?
個人認為如下:
1.?程序非法寫struct M的成員data,0xf3805ef0 ?地址位于堆上,此地址是可寫的。(如果是訪問.text代碼段地址的話,程序是會馬上終止的。)
2. malloc時,我推測內存管理模塊會check將要分配出的內存區域是否正常。?怎么檢查:比如,沒有分配出的內存區域設置為默認值或者魔數,如果發現有其它的非法值存在,就發生了非法寫,也就是說此內存還沒有被分配出去,就已經有code?對其做了寫操作。
根據之前內存池管理(https://blog.csdn.net/wowricky/article/details/83218126)的經驗,?內存管理模塊會在malloc和free時對內存區域進行檢查,如果存在異常會直接報錯memory corruption。所以malloc時的內存報錯,通常是由于之前的內存越界訪問導致的,這種問題通常比較難以定位。我碰到的這個問題比較幸運,非法訪問地址0xf3805ef0 ?是前一個動態內存區域[0xf3805b80,0xf3805e30)?操作不當導致的。
??
總結
以上是生活随笔為你收集整理的malloc为什么会报错:memory corruption的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 假字开头四字成语有哪些啊?
- 下一篇: 你还能认出这是马拉多纳么?