2011-07-22 11 views
8

新しいクラスのnew []、...演算子をクラスにオーバーロードして、ファイルと行をログに記録してメモリの割り当て/リークを簡単に追跡できるようにしました。新しい演算子のオーバーロードが発生しました。

今の問題は、私のスタックと配列クラス(およびメモリを割り当て、他のテンプレートコンテナクラス)である:

私は新しいを持っている私のクラスのいずれかでそれらを使用する場合は、新しいです[]、...演算子はそれがうまく動作するオーバーロードされます。

しかし、標準のC++データ型(int、float、...)で使用すると、オーバーロードされたnew演算子は新しい(__ LINE __、__ FILE __ )演算子(または新しい配置のようなもの)。スタックコードの

例:

// placement new 
T* t=new(__ LINE __ , __ FILE__)(&m_data[i])T; 

だから私はこの作業を行う方法について良いアイデアをよ。新しい(__ LINE __、__ FILE __)を新しいI loose memory logging能力で置き換えた場合。 1つの解決方法は、デフォルトのnewが使用されている標準のデータ型に対して別々のスタックを作成することです。

テンプレートパラメータが構造体、クラスまたは組み込みのC++型である場合、コンパイル時に検出する方法はありますか?

どのようにこのようなものを処理しますか? あなたは何をお勧めしますか? このデザインに関するコメント(良い、悪い)は明らかに歓迎されています(「自分のコンテナでホイールを再発明しない」など)。

+1

「メモリリークトレース」を下にこのようhereを追跡するメモリをやっについてtoturialがありますが、 '、オーバーロードがあります演算子new(__ LINE__、__FILE __) 'を使用し、' int'、 'float'などで使用しようとしましたか? – iammilind

+0

一つの選択肢は、グローバルな 'operator new()'と友達を置き換えることです。 – sharptooth

+5

メモリリークのデバッグでは、後になっていますが、なぜこのために既に存在するものの作業を行っているのか分かりません。Valgrind? – Nim

答えて

0
struct Int { 
    int i; 
    Int (int _i) : i(_i) {} 
    operator int() const {return i;} 
}; 

#define __LINE_NUMBER__ Int(__LINE__) 

このマクロを使用する代わりに、標準的な行番号マクロ過負荷分解能がint他の数字からInt行番号を識別します。

これがどのように機能するかは想像もできません。 int * x = NEW(int,123);のようなものを使っていますか?

私はコメント作成者に同意します。ところで、おそらくこの道を進む必要はありません。オーバーロードnewは黒い芸術の何かであり、通常避けるべきです。

+0

__LINE__マクロに問題はありません。それとも、私に何か他のことを教えたかったのですか? – n3XusSLO

+0

問題は、 '__LINE__'が、オーバーロードの解決に干渉するintを生成することです。ここでは、オーバーロードが異なるようにクラスにラップします。 – spraff

0

テンプレートパラメータは、構造体、クラス、または C++に建てタイプであれば、コンパイル時に検出する方法はありますか?

boos :: type_traitsとboost :: mplを使用できます。

例:

#include <boost/type_traits.hpp> 
#include <boost/mpl/not.hpp> 
#include <boost/mpl/logical.hpp> 

template <class T> 
typename boost::enable_if<boost::is_class<T>, T>::type 
foo(){cout << "is class " << endl;}; 

template <class T> 
typename boost::enable_if<boost::mpl::not_<boost::is_class<T> >, T>::type 
foo(){cout << "is not class "<< endl;}; 

種類一覧 - http://www.boost.org/doc/libs/1_47_0/libs/type_traits/doc/html/index.html

それとも、ブーストを使用することができます:: MPL ::セットタイプ

+0

私はまだこの問題を回避しようとしています。テンプレートクラスでは、テンプレートパラメータタイプに基づいてコンパイル時にデフォルトのnewまたはoverloaded newを使用するようコンパイラに選択させることができます新しいクラスをオーバーロードすることを選択しますが、それ以外の場合はデフォルトの新しいクラスを選択します)。 – n3XusSLO

1

のあなたのセットのためのあなたの現在のソリューションを追加する必要がありますのでご注意くださいログコードはになります。new(line, file)あなたは過負荷です。また、ログの呼び出しをそれぞれ#ifndef DEBUG ... #endifに囲まない限り、リリースビルドで簡単に無効にすることはできません。

は、ここでは、wnat何を達成するための一つの方法です。代わりにあなたのクラスごとnew演算子をオーバーロードの、配置構文を使用してグローバルnew演算子のオーバーロードを検討します。そうすれば、通常のnewオペレータとの干渉を避けることができます。その後、便宜のために#define新しいマクロと削除マクロを使用できます。最も重要なことは、メモリトラッキングnew/deleteが適用されているときと標準バージョンが使用されているときを制御できることです。

Allocated 1 byte(s) at address 00345008 in Alloc.cpp:58 
X::ctor() 
Allocated 1 byte(s) at address 003450B0 in Alloc.cpp:59 
X::ctor(20) 
X::dtor() 
Freed memory at address 00345008 
X::dtor() 
Freed memory at address 003450B0 

intためXを代入してみて、あなたはそれがあまりにも動作します表示されます:

#ifdef ENABLE_CUSTOM_ALLOC 

// Custom new operator. Do your memory logging here. 
void* operator new (size_t size, char* file, unsigned int line) 
{ 
    void* x = malloc(size); 
    cout << "Allocated " << size << " byte(s) at address " << x 
     << " in " << file << ":" << line << endl; 
    return x; 
} 

// You must override the default delete operator to detect all deallocations 
void operator delete (void* p) 
{ 
    free(p); 
    cout << "Freed memory at address " << p << endl; 
} 

// You also should provide an overload with the same arguments as your 
// placement new. This would be called in case the constructor of the 
// created object would throw. 
void operator delete (void* p, char* file, unsigned int line) 
{ 
    free(p); 
    cout << "Freed memory at address " << p << endl; 
} 

#define new new(__FILE__, __LINE__) 

#endif 


// A test class with constructors and destructor 
class X 
{ 
public: 
    X() { cout << "X::ctor()" << endl; } 
    X(int x) { cout << "X::ctor(" << x << ")" << endl; } 
    ~X() { cout << "X::dtor()" << endl; } 
}; 


int main (int argc, char* argv[]) 
{ 
    X* x3 = new X(); 
    X* x4 = new X(20); 
    delete x3; 
    delete x4; 
} 

次のようなものが表示されるはずです。これを配列と新しい配置に拡張することはできますが、私はむしろポストをそれより長くすることはできません。最後に

少数の最後のポインタ:
- MSVCがこの機能を持っている、here
を参照してください - セクション

関連する問題