VC程式調試的方法

來源:互聯網
上載者:User

標籤:style   blog   color   io   使用   ar   檔案   div   sp   

TRACE 使用方法與printf完全一致,在output框中輸出調試資訊

ASSERT 接收一個運算式,如果運算式為true,則無動作,否則終端當前程式執行,對於系統中出現這個宏導致的中斷,應該認為函數調用未能滿足系統的調用此函數的前提條件,例如,對於一個沒有建立的視窗調用setwindowtext

VERIFY和ASSERT功能類似,所不同的是,在Release版本中,ASSERT不計算運算式的值,而VERIFY計算運算式的值

幾個關於C/C++調試用到的函數

1調用棧系列

下面是函數原型

#include "execinfo .h"int backtrace(void **buffer, int size);char **backtrace_symbols(void *const *buffer, int size);void backtrace_symbols_fd(void *const *buffer, int size, int fd);

(1)backtrace用來擷取當前程式的調用棧,把結果存在buffer中。通常,我們用gdb偵錯工具,設定合適的斷點,停下來之後,用backtrce命令,就可以看到當前的調用棧,但是有時候,用到條件斷點的時候。gdb的功能就沒有程式本身的功能強大了,這個時候就可以考慮在程式中調用backtrace函數,來擷取調用棧。

(2)backtrace_symbols把用backtrace擷取的調用棧轉換成字串數組,以字串數組的形式返回,使用這需要在外面釋放返回的字串數組所佔用的記憶體

 

(3)backtrace_symbols_fd把用backtrace擷取的調用棧資訊寫到fd所指定的檔案中

void * __builtin_return_address (unsigned int level)

 這個函數用來得到當前函數,或者調用它的函數的返回地址,得到這個地址後,通過gdb反組譯碼,便可得到調用函數相關的資訊,這也是在應用中擷取調用棧的一種fangfa。

2記憶體配置釋放

#include "malloc .h"size_t malloc_usable_size((void *__ptr));

 這個函數的用法是返回調用malloc後實際分配的可用記憶體的大小,我們知道在c++中,operator new()可以重載各種各樣的版本,可以傳入調用的相關資訊來跟蹤記憶體配置情況。但是operator delete()卻只有兩種形式,不能隨意重載,尤其是全域的operator delete(),只有一種版本,這個時候就比較痛苦了,究竟釋放了多少記憶體,這時候malloc_usable_size()這個函數就有用武之地了,調用它就可以擷取當前釋放的記憶體大小,那麼在new中也請用他來統計開闢的記憶體,這樣才能對應起來,因為在調用malloc時很多時候實際分配記憶體會比使用者申請的要大一些,所以如果兩邊的統計方法對應不起來的話,統計結果也有比較大的判別

C++記憶體配置與管理

1函數

(1)operator new function

void * ::operator new(size_t);                //Globalvoid * class-name::operator new(size_t); //Class 

 上面是C++中operator new function的原型,一個是全域類型,一個的類成員類型,全域類型的operator new 函數在下面兩種情況下被調用:一種是在分配C++內建類型的動態記憶體時,一種是在分配使用者自己定義的operator new函數,那麼使用者在用new申請該類型的動態記憶體時,便會調用該類型的成員函數operator new,而不是全域的operator new。

另外,我們注意到,上面的原型中函數的傳回值void* 類型,第一個參數為size_t類型,這個是C++編譯要求的,如果要自己重載operator new函數,傳回值必須為void* 類型,第一個參數必須為size_t類型,否則,編譯器會返回如下錯誤資訊:

error: ‘operator new’ takes type ‘size_t’ (‘unsigned int’) as first parameter

 這裡需要注意的一點是,我們可以利用operator new function可以重載的特點,可以通過參數傳入一些額外的資訊,來偵錯工具,檢測記憶體泄露,比如,我們可以向下面這樣重載,傳調用處的行號,函數名,這樣就可以跟蹤記憶體的分配

void * operator new(size_t unSize, int nLine, const char * pFunc){    prinft("Line: %d, Func: %s, allocate %u byte(s)\n", nLine, pFunc, unSize);    return malloc(unSize);}

 (2)operator delete function

void operator delete( void * );void operator delete( void *, size_t );

 上面是operator delete function的原型,operator delete function也有全域和類成員的兩種,這壓力需要注意,一個類只能有一個operator delete function作為其成員函數,而且必須為上面兩種中的其中一種,沒有其他的形式,如果一個類實現了自己的operator delete function成員函數,那麼在釋放該類型的記憶體時,編譯器便會調用成員operator delete function,而不是全域的。

上面兩種原型,第一種在調用的時候,編譯器會把釋放的記憶體的首地址傳入,第二種在調用的時候,編譯器會把要釋放的記憶體的首地址和大小都傳入,因此,可以利用這一特性,如果我們在基類中實現第二種形式的operator delete function的成員函數,那麼便可以之來釋放子類類型的記憶體。

2 運算子

(1)new operator

[::] new [placement] new-type-name [new-initializer][::] new [placement] ( type-name ) [new-initializer]

 上面是new operator 的原型,在c++中,動態記憶體的分配,通常都是調用new operator來完成的,利用new operator來分配動態記憶體,編譯器要做下面兩項工作:

a. 調用operator new function 分配記憶體

b. 調用建構函式來進行初始化

下面來說一說new operator的原型中各部分到底是幹什麼的:

placement:如果你重載了operator new function,placement可以用來傳遞額外的參數

type-name:指定要分配的記憶體類型,可以是內建類型,也可以是使用者自訂類型

new-intializer:指定要分配後的記憶體的初始化參數,也就是建構函式的參數。這裡需要注意一點,在分配一個對象的數群組類型的記憶體時,不能夠指定初始化參數:換言之,想要分配一個對象的數群組類型的記憶體,該對象必須有預設建構函式

(2)delete operator

[::] delete cast-expression[::] delete [ ] cast-expression

 上面是delete operator的原型,第一種是用來釋放普通的物件類型的記憶體,第二種是用來釋放對象的數群組類型的記憶體,在C++中,用new operator分配的動態記憶體,必須調用delete operator來釋放,通常用delete operator 釋放記憶體編譯器要做下面兩箱工作:

a 調用對象解構函式來析構對象

b 調用operator delete function 來釋放記憶體

 3關於new/delete使用過程中一些需要注意的點

(1)如何區別operator new/ delete function與new/delete operator?

通過上面的講述,不難看出,我們分配/釋放動態記憶體,調用的是new/delete operator, 而在調用new/delete的過程中,編譯器會自動調用operator new/delete function來完成實際的記憶體配置/釋放的工作

(2) 用delete operator去釋放一塊不是由new operator釋放的記憶體,結果是不可預料的,因此,切記,operator new與operator delete一定要配對使用,這是寫好程式的基礎

(3) new operator調用失敗會拋出std::bad_alloc異常,前提是你沒有自己重載對應的operator new function;delete operator失敗,常見的原因是多次delete同一塊記憶體

(4) 如果一塊記憶體被delete後,再對它解引用(Dereference),結果也是不可預測的,很可能導致程式崩潰

(5) delete一個空(NULL)指標是安全的,沒有任何害處的

(6) 類成員類型的operator new/delete函數必須為靜態(static)函數,因此它們不能為虛函數(virtual function),也遵守public, protected, private的存取權限控制

 

VC程式調試的方法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.