malloc为什么会报错:memory corruption
最近遇到一個問題,很有意思,在此記錄下,以備后續(xù)參考。
程序運行異常,報錯:malloc: memory corruption.
用gdb?調(diào)試程序,bt?如下,程序在申請344 bytes內(nèi)存時失敗。
疑問:344bytes內(nèi)存并不大,為何會失敗呢?
進一步,打開AddressSanitizer,重選編譯并運行程序,AddressSanitizer報錯如下,報錯內(nèi)容分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 -?對應(yīng)內(nèi)存區(qū)域[0xf3805b80,0xf3805e30),?程序非法訪問的地址0xf3805ef0 位于此內(nèi)存區(qū)域右側(cè)的192個byte的位置。
3. Summary.
分析過程不必贅述,我把結(jié)論寫一下:
1.? 在*.c的507行分配了688個byte -?對應(yīng)內(nèi)存區(qū)域[0xf3805b80,0xf3805e30)
? ? 分析code,?發(fā)現(xiàn)這里是分配了2個結(jié)構(gòu)體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成員之前結(jié)構(gòu)體成員的長度為192.
?
注意cellGroupId的offset 和 size.
?
回味下面ASAN的提示:
0xf3805ef0 is located 192 byte to the right of 688-byte regin?[0xf3805b80,0xf3805e30)
由此可以推測:程序動態(tài)分配了2個struct M,?由于code?存在bug,?卻訪問了第三個struct M.?
最后進一步debug,發(fā)現(xiàn)程序確實是指針操作出錯,訪問了2個struct M后面的內(nèi)存。
思考:malloc失敗 與 AddressSanitizer: heap-buffer-overflow
沒有開啟AddressSanitizer時,程序?qū)憇truct M的成員data時并沒有直接報錯,而是延遲到再次malloc內(nèi)存時報錯?
個人認為如下:
1.?程序非法寫struct M的成員data,0xf3805ef0 ?地址位于堆上,此地址是可寫的。(如果是訪問.text代碼段地址的話,程序是會馬上終止的。)
2. malloc時,我推測內(nèi)存管理模塊會check將要分配出的內(nèi)存區(qū)域是否正常。?怎么檢查:比如,沒有分配出的內(nèi)存區(qū)域設(shè)置為默認值或者魔數(shù),如果發(fā)現(xiàn)有其它的非法值存在,就發(fā)生了非法寫,也就是說此內(nèi)存還沒有被分配出去,就已經(jīng)有code?對其做了寫操作。
根據(jù)之前內(nèi)存池管理(https://blog.csdn.net/wowricky/article/details/83218126)的經(jīng)驗,?內(nèi)存管理模塊會在malloc和free時對內(nèi)存區(qū)域進行檢查,如果存在異常會直接報錯memory corruption。所以malloc時的內(nèi)存報錯,通常是由于之前的內(nèi)存越界訪問導(dǎo)致的,這種問題通常比較難以定位。我碰到的這個問題比較幸運,非法訪問地址0xf3805ef0 ?是前一個動態(tài)內(nèi)存區(qū)域[0xf3805b80,0xf3805e30)?操作不當(dāng)導(dǎo)致的。
??
總結(jié)
以上是生活随笔為你收集整理的malloc为什么会报错:memory corruption的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 假字开头四字成语有哪些啊?
- 下一篇: gdb高级调试技巧