2009-07-14 11 views
5

私はメモリリークの検出は、これら2つの記事の助けを借りて作業を取得しようとしています: http://msdn.microsoft.com/en-us/library/e5ewb1h3%28VS.80%29.aspx http://support.microsoft.com/kb/q140858/メモリリーク新しい検出と上書き?

だから私は今持っている私のstdafx.hを中:

#define _CRTDBG_MAP_ALLOC 
#include <stdlib.h> 
#include <crtdbg.h> 

#define new new(_NORMAL_BLOCK,__FILE__,__LINE__) 

唯一の問題は、私です私はこのコードをコンパイルするとき、私が取得今

class Dummy 
{  
    //overloaded new operator 
    void FAR* operator new(size_t cb); 
} 

: エラーC2を新しい関数をオーバーライドするクラスを持っています059:構文エラー: '定数' エラーC2091:関数は関数を返します

どのように私はこれを修正できますか?

+0

これはマクロの問題です:( – GManNickG

+0

ウィンドウを使用していない場合は、valgrindをお勧めします。 – LiraNuna

+0

Windowsを使用している場合はDUMAを使用します。 – EFraim

答えて

9

オーバーロードの定義を解除すると、プラグマディレクティブを使用して新しいマクロを保存および復元できます。 。

#ifdef new 
#define NEW_WAS_DEFINED 
#pragma push_macro("new") 
#undef new 
#endif 

end_new_override.h::[MSDN](正確な構文についてhttp://msdn.microsoft.com/en-us/library/hsttss76(VS.71).aspx)

例:

#pragma push_macro("new") 
#undef new 
void FAR* operator new(size_t cb); 
#pragma pop_macro("new") 

あなたはヘッダにこれらを置くことができ、例えば

がbegin_new_override.hを参照してください。

#ifdef NEW_WAS_DEFINED 
#undef NEW_WAS_DEFINED 
#pragma pop_macro("new") 
#endif 

そして

#include "begin_new_override.h" 
void FAR* operator new(size_t cb); 
#include "end_new_override.h" 
+0

クールで、これは可能でした –

1

は、クラス定義 前 #undef new を試してみて、再度#define new new...後。

4

の代わりに別の何かであることが新たに定義し、なぜオペレータは、新たな過負荷になりませんか?

どこかにグローバル名前空間でこれらの関数定義を追加します。

// operator new overloads 
void* operator new(const size_t size, const char* file, int line) throw(); 
void* operator new(const size_t size, const size_t align, const char* file, int line) throw(); 
void* operator new[](const size_t size, const char* file, int line) throw(); 
void* operator new[](const size_t size, const size_t align, const char* file, int line) throw(); 

// can't easily overload operator delete 
void operator delete(void* ptr) throw(); 
void operator delete[](void* ptr) throw(); 

// matched to the operator new overload above in case of exceptions thrown during allocation 
void operator delete(void* ptr, const char* file, int line) throw(); 
void operator delete[](void* ptr, const char* file, int line) throw(); 
void operator delete(void* ptr, const size_t align, const char* file, int line) throw(); 
void operator delete[](void* ptr, const size_t align, const char* file, int line) throw(); 

// global new/delete 
void* operator new(size_t size) throw(); 
void* operator new(size_t size, const std::nothrow_t&) throw(); 
void* operator new(size_t size, size_t align) throw(); 
void* operator new(size_t size, size_t align, const std::nothrow_t&) throw(); 

void* operator new[](size_t size) throw(); 
void* operator new[](size_t size, const std::nothrow_t&) throw(); 

void operator delete(void* ptr, const std::nothrow_t&) throw(); 
void operator delete[](void* ptr, const std::nothrow_t&) throw(); 

を次にあなたが非グローバルのバージョンに至るまで呼び出す独自の新しいマクロを定義して、彼らは「場合主張または警告するグローバルなバージョンを実装することができます(何かを滑り込ませるために)呼び出されます。

#define MY_NEW(s) new(s, __FILE__, __LINE__) 

クラスで直接「新規」を呼び出すと、クラスレベルのオーバーロードが期待通りに機能します。クラスのMY_NEWを呼びたい場合は、新しいクラスに合わせてクラスのオーバーロードを再定義する必要があります。プリプロセッサレベルで#define経由newを再定義

+1

'__LINE__'は' char'ではなく 'int'です。 – Cornstalks

+0

新しい演算子と削除演算子の特定のオーバーロードを理解できました。 – Vinzenz

4

は、私の経験では悪い考えです - あなただけoperator new過負荷でなく、配置new、そしておそらくいくつか他のものを壊しません。

すべてのFILEマクロとLINEマクロを展開すると、.rodataセクションと.dataセクションがファイル文字列と行番号で膨らみ、呼び出しごとにさらに多くのコードが生成されます。

デバッグ情報(例えば、.pdbファイル)の存在を利用して、DbgHelpライブラリのStackWalk64のようなものを使用してスタック情報を収集する方がずっと優れています。

グローバル演算子newと演算子delete(array、nothrowなど)のさまざまな組み合わせをオーバーロードし、メモリが割り当てられて解放されるとスタック情報を格納して解放します。

この情報をstd :: map < void *、StackInfo >のような構造体に格納することもできます。マップ挿入によって発生したallocsを記録しないように注意してください(グローバルロックは、マルチスレッドは、読者の練習として残されています)。

allocのすべてのスタックを記録しているので、「関数と子孫」で割り振り(リークなど)をグループ化し、素晴らしいツリー解析を行うことができます。複雑なリーク割り当て時間からスタック全体を知っている場合。

+0

ちなみに、商用ソリューションを除いて、誰かがこの種のことを行うライブラリ/ツールキット(スタックトレース付きのalloc情報)を知っていたら、それについて聞いてみたいと思います。 。車輪を再発明する理由はありません。私が使用したバージョンは、組み込みプラットフォーム上にありました。 – leander

+1

ウィンドウでETWトレースを調べてみてください。このツールは無料で小さいので、デバッグに役立つようにクライアントマシンにドロップすることができます。また、アプリケーションから自分自身で追加の情報をetwトレースに投稿することもできます。メモリ割り当てと割り当て解除を追跡し、それぞれのスタック情報を取得できます。最も難しいことは、必要な情報を表示するためにWPAを設定することは難しいことです。 ここにリンクされている便利な動画がいくつかあります。 https://randomascii.wordpress.com/2014/08/19/etw-training-videos-available-now/ – 0xC0DEFACE

関連する問題