追蹤堆積配置要求
更新:2007 年 11 月
這個主題適用於:
版本 |
Visual Basic |
C# |
C++ |
Web Developer |
---|---|---|---|---|
Express 版 |
僅適用原生 |
|||
Standard 版 |
僅適用原生 |
|||
Pro/Team 版 |
僅適用原生 |
表格圖例:
套用 |
|
不套用 |
|
預設隱藏的命令。 |
雖然指出判斷提示或報告巨集執行的原始程式檔名稱和行號通常在找出問題原因很有用,但是對於堆積配置函式可能就不是這樣。雖然巨集可以插入到許多在應用程式邏輯樹狀圖裡合適的點,但是配置通常是在許多不同時間裡由許多不同地方的特殊常式呼叫。問題通常不是哪一行程式碼做了錯誤的配置,而是上千個配置中,哪一個配置是由哪一錯誤程式碼所造成,以及其錯誤原因為何。
唯一配置要求號碼和 _crtBreakAlloc
最簡單的辨識發生錯誤的特定堆積配置呼叫方法,是利用與偵錯堆積裡每個區塊相關的唯一配置要求編號。當區塊的相關資訊由其中一個傾印函式報告時,這個配置要求編號會包含在大括號裡 (例如 "{36}")。
一旦您知道不適當配置區塊的配置要求編號時,您可以將這個編號傳入至 _CrtSetBreakAlloc 來建立中斷點。執行會在配置區塊之前中斷,而您即可回溯追蹤以判斷哪一個常式要對這個錯誤呼叫負責。若要避免重新編譯,您可以在偵錯工具裡將 _crtBreakAlloc 設定為您要的配置要求編號,來完成相同的事。
建立配置常式的偵錯版本
較複雜的方法是建立您自己的配置常式的偵錯版本,其須與堆積配置函式的 _dbg 版本相容。然後您可以傳遞原始程式檔和行號引數到下面的堆積配置常式,而且立即能夠看到錯誤的配置的發生位置。
例如,假設應用程式包含一個類似下列的一般使用常式:
int addNewRecord(struct RecStruct * prevRecord,
int recType, int recAccess)
{
// ...code omitted through actual allocation...
if ((newRec = malloc(recSize)) == NULL)
// ... rest of routine omitted too ...
}
您可以在標頭檔 (Header File) 裡加入像這樣的程式碼:
#ifdef _DEBUG
#define addNewRecord(p, t, a) \
addNewRecord(p, t, a, __FILE__, __LINE__)
#endif
接著,您可以依照下列示範方式,在記錄建立常式裡變更配置:
int addNewRecord(struct RecStruct *prevRecord,
int recType, int recAccess
#ifdef _DEBUG
, const char *srcFile, int srcLine
#endif
)
{
/* ... code omitted through actual allocation ... */
if ((newRec = _malloc_dbg(recSize, _NORMAL_BLOCK,
srcFile, scrLine)) == NULL)
/* ... rest of routine omitted too ... */
}
現在,偵錯堆積中每個產生的配置區塊,都會儲存呼叫 addNewRecord 位置的原始程式檔名稱和行號,而區塊檢查時也會報告這些資訊。