1. 程式人生 > >例項介紹利用valgrind定位記憶體異常釋放問題(double free 和wrong free)

例項介紹利用valgrind定位記憶體異常釋放問題(double free 和wrong free)

         之前介紹過利用valgrind來定位記憶體洩漏(慢性病, 會導致程式在某個不確定的時刻異常), 本文我們來簡要介紹利用valgrind來定位記憶體的重複釋放(急性病, 會報紙程式崩潰)。 看程式:

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

int main()
{
	char *p = (char *)malloc(30);
	free(p);
	free(p);

    return 0;
}
       我們用valgrind來檢測一下:
[[email protected]
~/valgrind-3.8.1/bin]# g++ -g test.cpp [[email protected] ~/valgrind-3.8.1/bin]# [[email protected] ~/valgrind-3.8.1/bin]# ./valgrind --tool=memcheck --leak-check=yes --show-reachable=yes ./a.out ==18229== Memcheck, a memory error detector ==18229== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==18229== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==18229== Command: ./a.out ==18229== ==18229== Invalid free() / delete / delete[] / realloc() ==18229== at 0x4C27300: free (vg_replace_malloc.c:446) ==18229== by 0x400611: main (test.cpp:9) ==18229== Address 0x5d84040 is 0 bytes inside a block of size 30 free'd ==18229== at 0x4C27300: free (vg_replace_malloc.c:446) ==18229== by 0x400605: main (test.cpp:8) ==18229== ==18229== ==18229== HEAP SUMMARY: ==18229== in use at exit: 0 bytes in 0 blocks ==18229== total heap usage: 1 allocs, 2 frees, 30 bytes allocated ==18229== ==18229== All heap blocks were freed -- no leaks are possible ==18229== ==18229== For counts of detected and suppressed errors, rerun with: -v ==18229== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6) [
[email protected]
~/valgrind-3.8.1/bin]#

      很容易看到, 第9行錯誤釋放(重複釋放)。 如果直接執行a.out程式, 會出現什麼問題呢?  程式直接崩潰了, abort了, 如下:

[[email protected] ~/valgrind-3.8.1/bin]# ./a.out 
*** glibc detected *** ./a.out: double free or corruption (fasttop): 0x00000000011b1010 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x75e66)[0x7f9877755e66]
./a.out[0x400612]
/lib64/libc.so.6(__libc_start_main+0xfd)[0x7f98776fed5d]
./a.out[0x400529]
======= Memory map: ========
00400000-00401000 r-xp 00000000 fd:01 562221                             /root/valgrind-3.8.1/bin/a.out
00600000-00601000 rw-p 00000000 fd:01 562221                             /root/valgrind-3.8.1/bin/a.out
011b1000-011d2000 rw-p 00000000 00:00 0                                  [heap]
7f98772bf000-7f98772d6000 r-xp 00000000 fd:01 309668                     /lib64/libpthread-2.12.so
7f98772d6000-7f98774d6000 ---p 00017000 fd:01 309668                     /lib64/libpthread-2.12.so
7f98774d6000-7f98774d7000 r--p 00017000 fd:01 309668                     /lib64/libpthread-2.12.so
7f98774d7000-7f98774d8000 rw-p 00018000 fd:01 309668                     /lib64/libpthread-2.12.so
7f98774d8000-7f98774dc000 rw-p 00000000 00:00 0 
7f98774dc000-7f98774de000 r-xp 00000000 fd:01 309538                     /lib64/libdl-2.12.so
7f98774de000-7f98776de000 ---p 00002000 fd:01 309538                     /lib64/libdl-2.12.so
7f98776de000-7f98776df000 r--p 00002000 fd:01 309538                     /lib64/libdl-2.12.so
7f98776df000-7f98776e0000 rw-p 00003000 fd:01 309538                     /lib64/libdl-2.12.so
7f98776e0000-7f987786a000 r-xp 00000000 fd:01 309509                     /lib64/libc-2.12.so
7f987786a000-7f9877a6a000 ---p 0018a000 fd:01 309509                     /lib64/libc-2.12.so
7f9877a6a000-7f9877a6e000 r--p 0018a000 fd:01 309509                     /lib64/libc-2.12.so
7f9877a6e000-7f9877a6f000 rw-p 0018e000 fd:01 309509                     /lib64/libc-2.12.so
7f9877a6f000-7f9877a74000 rw-p 00000000 00:00 0 
7f9877a74000-7f9877a8a000 r-xp 00000000 fd:01 309558                     /lib64/libgcc_s-4.4.6-20110824.so.1
7f9877a8a000-7f9877c89000 ---p 00016000 fd:01 309558                     /lib64/libgcc_s-4.4.6-20110824.so.1
7f9877c89000-7f9877c8a000 rw-p 00015000 fd:01 309558                     /lib64/libgcc_s-4.4.6-20110824.so.1
7f9877c8a000-7f9877d0d000 r-xp 00000000 fd:01 309608                     /lib64/libm-2.12.so
7f9877d0d000-7f9877f0c000 ---p 00083000 fd:01 309608                     /lib64/libm-2.12.so
7f9877f0c000-7f9877f0d000 r--p 00082000 fd:01 309608                     /lib64/libm-2.12.so
7f9877f0d000-7f9877f0e000 rw-p 00083000 fd:01 309608                     /lib64/libm-2.12.so
7f9877f0e000-7f9877ff6000 r-xp 00000000 fd:01 171070                     /usr/lib64/libstdc++.so.6.0.13
7f9877ff6000-7f98781f6000 ---p 000e8000 fd:01 171070                     /usr/lib64/libstdc++.so.6.0.13
7f98781f6000-7f98781fd000 r--p 000e8000 fd:01 171070                     /usr/lib64/libstdc++.so.6.0.13
7f98781fd000-7f98781ff000 rw-p 000ef000 fd:01 171070                     /usr/lib64/libstdc++.so.6.0.13
7f98781ff000-7f9878214000 rw-p 00000000 00:00 0 
7f9878214000-7f9878234000 r-xp 00000000 fd:01 309485                     /lib64/ld-2.12.so
7f987830f000-7f9878314000 rw-p 00000000 00:00 0 
7f9878322000-7f9878323000 rw-p 00000000 00:00 0 
7f9878323000-7f9878326000 r-xp 00000000 fd:01 309900                     /lib64/libonion_security.so.1.0.13
7f9878326000-7f9878426000 ---p 00003000 fd:01 309900                     /lib64/libonion_security.so.1.0.13
7f9878426000-7f9878427000 rw-p 00003000 fd:01 309900                     /lib64/libonion_security.so.1.0.13
7f9878427000-7f9878433000 rw-p 00000000 00:00 0 
7f9878433000-7f9878434000 r--p 0001f000 fd:01 309485                     /lib64/ld-2.12.so
7f9878434000-7f9878435000 rw-p 00020000 fd:01 309485                     /lib64/ld-2.12.so
7f9878435000-7f9878436000 rw-p 00000000 00:00 0 
7fffc2f9b000-7fffc2fbc000 rw-p 00000000 00:00 0                          [stack]
7fffc2ffe000-7fffc3000000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted
[
[email protected]
~/valgrind-3.8.1/bin]#
      

       如果是這種程式呢?

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

int main()
{
	char szTest[100] = {0};
	char *p = szTest;
	free(p);

    return 0;
}
      編譯執行一下:
[[email protected] ~/valgrind-3.8.1/bin]# g++ -g test.cpp
[[email protected] ~/valgrind-3.8.1/bin]# ./a.out 
Segmentation fault
[[email protected] ~/valgrind-3.8.1/bin]# ulimit -c unlimited
[[email protected] ~/valgrind-3.8.1/bin]# ./a.out 
Segmentation fault (core dumped)
[[email protected] ~/valgrind-3.8.1/bin]# 
[[email protected] ~/valgrind-3.8.1/bin]# 
[[email protected] ~/valgrind-3.8.1/bin]# 
[[email protected] ~/valgrind-3.8.1/bin]# ./valgrind --tool=memcheck --leak-check=yes --show-reachable=yes ./a.out
==22452== Memcheck, a memory error detector
==22452== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==22452== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==22452== Command: ./a.out
==22452== 
==22452== Invalid free() / delete / delete[] / realloc()
==22452==    at 0x4C27300: free (vg_replace_malloc.c:446)
==22452==    by 0x4005DC: main (test.cpp:9)
==22452==  Address 0x7ff000470 is on thread 1's stack
==22452== 
==22452== 
==22452== HEAP SUMMARY:
==22452==     in use at exit: 0 bytes in 0 blocks
==22452==   total heap usage: 0 allocs, 1 frees, 0 bytes allocated
==22452== 
==22452== All heap blocks were freed -- no leaks are possible
==22452== 
==22452== For counts of detected and suppressed errors, rerun with: -v
==22452== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6)
[[email protected] ~/valgrind-3.8.1/bin]# 
      可以看到, 程式直接崩潰, segment fault了, 如果開啟core開關, 看可以看到core dump的檔案。 在這種情況下, 我們也可以利用valgrind來檢測。

      OK, 先說這麼多。

相關推薦

例項介紹利用valgrind定位記憶體異常釋放問題double free wrong free

         之前介紹過利用valgrind來定位記憶體洩漏(慢性病, 會導致程式在某個不確定的時刻異常), 本文我們來簡要介紹利用valgrind來定位記憶體的重複釋放(急性病, 會報紙程式崩潰)。 看程式: #include <stdio.h> #inc

例項介紹利用valgrind定位記憶體洩漏問題

        在前面的文章中, 我們簡單瞭解了valgrind工具的用途以及安裝, 以便大家能進行實際操作。 在本文中, 我們通過例項來看看如何利用valgrind來定位記憶體洩漏問題。 先看程式: #include <stdio.h> #include &

例項介紹利用valgrind定位記憶體非法訪問問題

       本文繼續介紹 valgind的使用, 看程式: #include <stdio.h> int main() { int a[100]; a[10000] = 0; return 0; }       用valgrind分

利用python輸出乘法口訣表正序倒序

This is my first csdn. 正序如下: for i in range(1,10):     for j in range(1,i+1):         print(str(i)+"*"+str(j)+"="+str(i*j),end=" ")    

利用工具定位記憶體洩漏問題 valgrind memwatch dmalloc

記憶體洩漏定位工具 記憶體debug有比較多的方法,首先可以參看如下的wiki,檢視大概都有哪些方式,再根據其有缺點選用,適合自己需要的方式。 Memory Debuggers https://elinux.org/Memory_Debuggers#mpatrol

c語言中記憶體的動態分配與釋放多維動態陣列構建

一. 靜態陣列與動態陣列    靜態陣列比較常見,陣列長度預先定義好,在整個程式中,一旦給定大小後就無法再改變長度,靜態陣列自己自動負責釋放佔用的記憶體。    動態陣列長度可以隨程式的需要而重新指定大小。動態陣列由記憶體分配函式(malloc)從堆(heap

Tensorflow例項利用LSTM預測股票每日最高價

根據股票歷史資料中的最低價、最高價、開盤價、收盤價、交易量、交易額、跌漲幅等因素,對下一日股票最高價進行預測。 實驗用到的資料長這個樣子: label是標籤y,也就是下一日的最高價。列C——I為輸入特徵。 本例項用前5800個數據做訓練資料。

Tensorflow例項利用LSTM預測股票每日最高價

這一部分主要涉及迴圈神經網路的理論,講的可能會比較簡略。 什麼是RNN RNN全稱迴圈神經網路(Recurrent Neural Networks),是用來處理序列資料的。在傳統的神經網路模型中,從輸入層到隱含層再到輸出層,層與層之間是全連線的,每層之間

Windows批處理檔案.bat檔案.cmd檔案介紹以及簡單使用

首先說一下cmd檔案和bat檔案的區別,從檔案描述中的區別是,cmd檔案叫做:Windows命令指令碼,bat檔案叫:批處理檔案,兩者都可以使用任意一款文字編輯器進行建立、編輯和修改,只是在cmd中支援的命令要多於bat。 批處理檔案是一種沒有什麼固定格式的檔案,他可以處理一條或者多條命令,

異常處理程式健壯性→功能→效能

  異常 (Exception):發生於程式執行期間,表明出現了一個非法的執行狀況。許多JDK中的方法在檢測到非法情況時,都會丟擲一個異常物件。例如:陣列越界和被0除。 try{   //可能發生執行錯誤的程式碼;  }  

解決Tomcat記憶體溢位問題java.lang.OutOfMemoryError: PermGen space

常見原因: jvm記憶體過小 程式不夠嚴謹,產生了過多的辣雞 解決方案: 增加jvm記憶體 步驟: step1:在Servers視窗雙擊使用的tomcat step2:在彈出的視窗中選擇Open launch configurat

異常2----異常處理try...cache...finally、throws

二、try...catch異常處理 當執行程式時,可能丟擲異常。可以對可能出現異常的程式捕獲異常並處理。【例1】 當呼叫帶有throws的方法(指可能丟擲非RuntimeExce

➢《利用Python進行資料分析》原書第2版|書籍分享

《利用Python進行資料分析》(原書第2版) 英: Python for Data Analysis: Data Wrangling with Pand 適讀人群 :適合剛學Python的資料分析師或剛學資料科學以及科學計算的Python程式設計者。 閱

EOS實戰RPC介面使用RPC的介面建立賬戶同時購買記憶體併為其抵押CPUNET資源

1. 前言 前面我們使用RPC API完成了轉賬。這篇文章繼續使用RPC API來建立賬號。在EOS中,這些行為都叫做transaction,更本質一點說是一筆transaction中的action。在轉賬的transaction中,只有一個action,它呼叫eosio.

利用theano編寫logistic迴歸模型A Real Example: Logistic Regression

A Real Example: Logistic Regression 程式碼註釋的已經比較詳細,請仔細閱讀! import numpy import theano import theano.tensor as T import matplotlib.pyp

利用 Postman-同步瀏覽器登入狀態postman介面傳入登入態

一、先安裝Postman,Postman  Interceptor(Chrome商店搜尋); 二、點選chrome上相應圖示,點選Postman Chrome app 三.開啟postman,開啟這個配置     這時候在postman中,就可

異常層次結構及異常處理try、catch、finally

在Java程式語言設計中,所有的異常都是由類來表示,異常物件都是派生於Throwable類的一個例項。下面是Java異常層析結構的一個簡單示意圖: 由圖可知,所有異常類都直接或間接的繼承於Throwable類。 具體分類: Java把所有非正常情況分為Error(錯

記憶體記憶體的區別一個筆試題的一部分

筆試題目:請解釋一個棧記憶體與一個堆記憶體的區別,請分析下面程式碼執行是否有問題,如果有問題請改正。 char* GetMemory(void) {      char p[] = "Hello world";      return p; } void main(void

Python記憶體管理二 arena快取池

接上文: 2.1  arean 多個pool聚合起來就是arean了,當然它也有預設的大小,一般是256k,包含的poo的個數就是256 / 4 = 64 個 先看下arean:  struct arena_object { uptr address;    

libevent簡單介紹以及使用帶有伺服器客戶端

這兩天使用了下libevent,只使用了網路IO事件(EV_READ和 EV_WRITE),查閱了下libevent的介面文件,這裡做點筆記,並附上程式碼,開發環境是win7+vs2010 這裡只介紹需要用到的libevent的介面函式,更多介面函式請檢視libevent官方文件 如果想了解