6

大きなクローズド ソース アプリケーション用のプラグイン (dll として実装) を維持しています。これは何年もうまく機能しています。ただし、SDK の最新の更新では、ベンダーがグローバル オペレーター new および delete をオーバーロードしました。これは私に多くの問題を引き起こします。何が起こるかというと、プラグインが文字列を割り当てます。この文字列を、それを変更する静的にリンクされたライブラリに渡します (長さを変更して再割り当てします)。アプリケーションがクラッシュします。

その理由はもちろん、文字列がベンダーによって割り当てられたカスタム ヒープに存在するためです。静的にリンクされたライブラリは、このヒープについて何も認識せず、そのメモリでデフォルトの new/delete 演算子を使用しようとします。ブーム。

問題は、コードをクリーンに保ち、ベンダーの演算子を使用しないようにするにはどうすればよいかということです。条件付きプリプロセッサ マクロはありません。プラグインに必要な 2000 行以上のコードが含まれているため、問題のあるヘッダーを含めることは避けられません。提供されたアロケーターを他のライブラリーに渡すことはできません。そのためのメカニズムが提供されていないためです。私はすでにそれについてベンダーに盗聴しました。他に何を試すことができるかわかりませんか?

補遺:いくつかの激しい議論の後、私はベンダーに、SDK の次のバージョンからオーバーロードを再度削除するよう説得することができました。現在の SDK をハッキングしてオーバーロードを手動で削除するだけで、差し迫った問題を解決できました。このスレッドのすべての提案に感謝します。それらは引数として機能し、オーバーロードが最初に悪い考えであった理由のさらなる「証拠」として機能しました。

4

4 に答える 4

5

オーバーライドされた new/delete 演算子を (ヘッダー インクルード経由で) コンパイルしている場合、コード内の new/delete へのすべての呼び出しでそれらが使用されます。それを再オーバーライドする方法はありません (リンク エラー)、または部分的にしかオーバーライドしないなどです。

グローバルな new/delete 演算子をオーバーライドするのは、まったく悪い形式です。それは悪い考えです。なぜそれが悪い考えなのかがわからない場合は、そうする資格がありません。なぜそれが悪い考えであるかを理解していれば、そうする資格がありますが、通常はそうしないことを選択します。

グローバルな新規/削除を定義することは、人々がプロジェクトに直接含めることを期待するコンポーネントでは、指数関数的により邪悪です。これを行っているベンダーが状況の深刻さを理解するのを助けるか、または彼らの顧客であるのをやめさせるのは、顧客としてのあなたの仕事です.

カスタム アロケーター型を定義し (その方法、必要なインターフェイスなどに関する優れたチュートリアルについては、このリンクを参照してください)、それを STL 型 (テンプレート引数) だけで使用できます。

shared_ptr の場合、少し異なることを行う必要があります。デフォルトの「delete p」動作が必要ない場合は、コンストラクターへのパラメーターとして deleter オブジェクトを使用します。これはカスタム アロケーターではありません。それは単なる通常の単項関手です。

于 2010-01-05T19:19:56.567 に答える
2

これを行うことはできませんか:

namespace evil{

#include "evil_header.h"

}

次に、evil_header がグローバルな new/delete として宣言するものは、evil::new/evil::delete になります。ただし、evil_header で宣言されているもののヘッダー以外の定義がある場合、これがうまく機能するとは思えません。

于 2010-01-05T19:54:03.503 に答える
1

名前空間で別の新しいものを使用できます。

namespace MyNS {
    // Declare your new/delete operators here
    // and also declare a class implementing the same interface as std::allocator
    // using your newly created memory management functions.
    // Don't forget to put all your classes in the namespace.
    // (if you don't have one already)
}

その後、すべてのSTLクラスを使用して、テンプレート引数としてアロケータタイプを指定できます。

于 2010-01-05T16:51:33.977 に答える
0

1 つのオプションは、malloc に関して実装できる独自のオーバーロードされた新しい演算子を作成することです。

これは次のように定義できます。

enum MyNew {EMyNew};

void *operator new(size_t size, MyNew);

これは、次のように呼び出すことができます。MyClass* myClass = new (EMyNew)MyClass;

これは malloc の観点から実装されているため、期待どおりに動作するはずです。唯一の欠点は、new を使用した場所のすべてのインスタンスを置き換える必要があることです。

于 2010-01-05T16:17:07.187 に答える