2014-10-06 45 views
0

所以這是首要的家庭作業項目。我的整個程序正在運行,這是一個處理動態內存分配的中間/高級項目。我無法弄清楚如何顯示正常輸出的行數。我試圖看看關於這個主題的其他問題,但我似乎無法找出幫助我的原因。有關如何設置行號的任何建議?內存泄漏。行號

這裏是我的"LeakWatcher.cpp"

#ifndef IMWATCHINGYOULEAK 
#define IMWATCHINGYOULEAK 
#define _CRTDBG_MAP_ALLOC 
#include <stdlib.h> 
#include <crtdbg.h> 
#ifdef _DEBUG 
inline void* operator new(size_t nSize, const char * lpszFileName, int nLine) 
{ return ::operator new(nSize, 1, lpszFileName, nLine); } 
inline void __cdecl operator delete(void * _P, const char * lpszFileName, int nLine) 
{ ::operator delete(_P, _NORMAL_BLOCK, lpszFileName, nLine); } 
#define DEBUG_NEW new(__FILE__, __LINE__) 
#define MALLOC_DBG(x) _malloc_dbg(x, 1, __FILE__, __LINE__); 
#define malloc(x) MALLOC_DBG(x) 
#define new DEBUG_NEW 
#endif // _DEBUG 
#endif // #include guard 

而且我main()

int main() 
{ 
    _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); 
    _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT); 
    _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); 
    _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT); 
    _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); 
    _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT); 

    try 
    { 
     Directory().Run(); 
    } 
    catch (...) 
    { 
     cout << "Uncaught Exception" << endl; 
    } 

    _CrtDumpMemoryLeaks(); 

    return 0; 
} 
+0

您是否嘗試過打印'__FILE__'或'__LINE__'? – gldraphael 2014-10-06 21:42:35

+0

你的問題沒有任何意義。你說什麼「正常輸出」?據我所知,這裏根本沒有輸出代碼(除了「catch」外 - 就是你在說什麼?)。什麼阻止你輸出行號在你想要的時間和地點? – 2014-10-06 21:42:50

+0

@DavidSchwartz:這似乎是MS VC++代碼。如果檢測到泄漏,_CrtDumpMemoryLeaks會將信息轉儲到控制檯。 – 2014-10-06 21:49:27

回答

1

根據您的代碼確實發生的事情是這樣的。你說你把所有的調試宏放到了LeakWatcher.cpp而不是LeakWatcher.h。我懷疑這是你的問題。

使用LeakWatcher.cpp中的所有內容創建LeakWatcher.h。你不需要LeakWatcher.cpp,所以你應該能夠刪除它。現在使用#include "LeakWatcher.h"頂部的全部.cpp文件。所以它看起來像下面這樣。

文件LeakWatcher.h

#ifndef IMWATCHINGYOULEAK 
#define IMWATCHINGYOULEAK 
#define _CRTDBG_MAP_ALLOC 
#include <stdlib.h> 
#include <crtdbg.h> 
#ifdef _DEBUG 
inline void* operator new(size_t nSize, const char * lpszFileName, int nLine) 
{ return ::operator new(nSize, 1, lpszFileName, nLine); } 
inline void __cdecl operator delete(void * _P, const char * lpszFileName, int nLine) 
{ ::operator delete(_P, _NORMAL_BLOCK, lpszFileName, nLine); } 
#define DEBUG_NEW new(__FILE__, __LINE__) 
#define MALLOC_DBG(x) _malloc_dbg(x, 1, __FILE__, __LINE__); 
#define malloc(x) MALLOC_DBG(x) 
#define new DEBUG_NEW 
#endif // _DEBUG 
#endif // #include guard 
TEST.CPP文件

然後你就可以做到這一點(類似測試代碼):

#include "LeakWatcher.h" 

int main() 
{ 
    _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); 
    _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT); 
    _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); 
    _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT); 
    _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); 
    _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT); 

    new int[40]; // This should be a memory leak 

    _CrtDumpMemoryLeaks(); // This should dump with line numbers and file names 

    return 0; 
} 

當然會僅在您正在構建項目的debug版本時纔有效。

爲了得到一些其他見解覆蓋這些堆例程,我發現這個MSDN Article有價值。

+0

這與我正在查找的內容最爲接近,但是我的Visual Studios將不會打印出正在發生的行號。它將該行保留。 – Adam 2014-10-06 22:59:56

+0

我在VS2010和VS2013上試過上面的代碼。您是否偶然使用Express版本?當我按照您所描述的方式處理您的代碼並嘗試使用'_CrtDumpMemoryLeaks()'顯示的泄漏內存中沒有行號和文件名。在做了我的修改並做了它之後,'_CrtDumpMemoryLeaks()'輸出塊信息以及文件名和行號。一旦你創建了頭文件('LeakWatcher.h'),你需要確保你將它包含在** all **你的cpp文件中。所以如果你有多個cpp文件,你需要爲每個文件添加一個'#include「LeakWatcher.h」'。 – 2014-10-06 23:06:24

+0

我也這麼做了。它仍然留下行號。這是在每個.cpp文件中包含「LeakWatcher.h」之後。而且我沒有使用Professional。 – Adam 2014-10-06 23:07:13

0

我相信你問一個已經分配但未被髮布跟蹤的內存的實際算法。

保持跟蹤您的內存分配請求來自的那個生產診斷輸出的目的的典型方法如下:

  1. 說你要跟蹤的主叫方請求n_bytes值得記憶。

  2. 分配n_bytes + sizeof(const char *)+ sizeof(int)。

  3. 商店FILELINE在分配內存的第一部分,並返回分配內存的其餘部分理應什麼被分配。

事情是這樣的:

struct hdr { 
    const char *file; 
    int line; 
}; 

void *my_allocation_request(const char *file, int line, size_t nbytes) 
{ 
    struct hdr *p=(struct hdr *)malloc(nbytes+sizeof(hdr)); 

    p->file=file; 
    p->line=line; 

    // Here be dragons 

    return (void *)(p+1); 
} 

(據推測,您的new運營商送過來踢)。

類似的,當事情要解除分配的內存塊

void my_deallocation_request(char *p) 
{ 
    struct hdr *h=reinterpret_cast<hdr *>(p+1); 

    // Here be dragons 

    free(h); 
} 

之前這可能是一個最終的解決方案,你還需要編寫更多的代碼,進入「這裏是龍」的一部分,我想你大概可以自己弄明白:

A)把每個新分配的內存,並把它放在某種類型的列表(龍的第一個位置)。

B)從某種列表中刪除分配的內存(龍的第二個位置)。

然後,在程序結束時,您可以查看列表中剩下的任何內容。這將是你的泄漏內存,並且你將擁有文件和分配給它的行號。

請注意,您可能需要手動實現未釋放內存塊的鏈接列表。使用某個標準容器可能會導致無限循環,因爲容器非常合理地期望能夠爲自己的使用分配內存,這將循環回到您自己的新/刪除攔截中,這會要求容器分配更多的內存,它將循環回你自己的新/刪除攔截等等。

這裏可能有一些實現特定的問題,關於對齊分配的內存,但這不太可能,而且現在可能會忽略這種分裂現象。