2

ロギングのために、グローバルおよび非グローバルの new/delete 演算子をオーバーロードしたいと考えています。

ロギング情報を追加したいだけなので、この演算子の標準的な動作を維持したいと思います。

new/delete 演算子をオーバーロードしてログを追加する方法はありますが、標準の動作を書き直す必要はありません (エラーが発生しやすい可能性があります)。

実際には、標準的な動作だけが必要なわけではありません。Visual 2010 の実装と同じ動作が必要ですが、標準ではない可能性があります。

この種のロギングで探しているエラーの種類は、new[]/delete の不一致です。

従来のツールを使用することもできましたが、実行速度が遅くなったため、バイナリを他の人と共有してより多くの情報を収集したいと考えています。

4

2 に答える 2

4

基本的な割り当てにはmalloc/を使用できます。freeの完全な標準準拠を処理するのnewは少し注意が必要です。次のようなものが必要です:

void*
operator new( size_t n )
{
    void* results = malloc( n );
    while ( results == NULL ) {
        if ( std::get_new_handler() == NULL ) {
            throw std::bad_alloc();
        }
        (*std::get_new_handler())();
        results = malloc( n );
    }
    return results;
}

ただし、多くの場合、このような完全なコンプライアンスは必要ありません。たとえば、の設定をサポートしていないと言う場合はnew_handler、大幅に簡略化できます。テストに使用するオーバーロードされたバージョンでは、malloc実際に失敗した場合は中止します(ただしnew、コードが正しく反応することをテストしたいので、このバージョンには、オンデマンドでの失敗をトリガーするオプションがあります)。

ログに記録する場合は、無限の再帰を回避するように十分に注意してください。operator new標準ライブラリで使用されないことが保証されている関数はmalloc、とだけfreeです。もちろん、動的に割り当てる理由は多くないので、やのような関数については心配しませmemcpystrlen。実際には、Cライブラリの関数のいずれかを使用してもおそらく安全です(理論printf的には、の観点から実装できますiostream)。ただし、再帰から保護しない限り、iostream、ロケール、または標準コンテナは使用できません。

void*
operator new( size_t n )
{
    static int recursionCount = 0;
    ++ recursionCount;
    void* results = malloc() ;
    //  Any additional logic you need...
    if ( recursionCount == 1 ) {
        logAllocation( results, n );
    }
    -- recursionCount;
    return results;
}

正式には、同じことを行う必要がありますoperator deleteが、実際には、ファイルにログを記録している場合は、またはデストラクタdelete 以外は期待していません。close()

于 2012-09-13T09:49:09.457 に答える
0

キーワードを再定義してnew、別の署名やパスなどを呼び出すことができ__FILE__ます。

一般的なケースでは、これで問題ありません。オーバーライドするオブジェクトを使い始めるとoperator new、ちょっと面倒になります。

記憶で知っていれば共有しますが、おそらくGoogleで見つけることができます。コードプロジェクトのどこかに実装があると思います。

于 2012-09-13T09:39:49.877 に答える