多くの理由で、私が作業しているグローバルな new および delete 演算子をオーバーロードします。
- すべての小さな割り当てをプールする -- オーバーヘッドを減らし、断片化を減らし、小さな割り当てが多いアプリのパフォーマンスを向上させることができます
- 有効期間がわかっている割り当てのフレーミング-- この期間が終了するまですべての解放を無視し、次にすべてをまとめて解放します (確かに、グローバルよりもローカルの演算子のオーバーロードでこれを行います)。
- アライメント調整 -- キャッシュライン境界など
- alloc fill -- 初期化されていない変数の使用法を公開するのに役立ちます
- free fill -- 以前に削除されたメモリの使用状況を明らかにするのに役立ちます
- フリーの遅延-- フリー フィルの有効性が向上し、パフォーマンスが向上する場合があります
- センチネルまたはフェンスポスト-- バッファー オーバーラン、アンダーラン、および時折発生するワイルド ポインターを明らかにするのに役立ちます
- 割り当てのリダイレクト-- NUMA、特別なメモリ領域を考慮したり、個別のシステムをメモリ内で分離しておくこともできます (埋め込みスクリプト言語や DSL など)。
- ガベージ コレクションまたはクリーンアップ -- これらの埋め込みスクリプト言語に再び役立ちます
- ヒープ検証-- N 個の allocs/frees ごとにヒープ データ構造を調べて、すべてが正常に見えることを確認できます。
- リーク追跡と使用状況のスナップショット/統計(スタック、割り当て期間など)を含むアカウンティング
新規/削除アカウンティングの考え方は非常に柔軟で強力です。たとえば、割り当てが発生するたびにアクティブなスレッドのコールスタック全体を記録し、それに関する統計を集計できます。何らかの理由でスタック情報をローカルに保持するスペースがない場合は、ネットワーク経由でスタック情報を送信できます。ここで収集できる情報の種類は、想像力 (およびもちろんパフォーマンス) によってのみ制限されます。
グローバル オーバーロードを使用するのは、そこに多くの一般的なデバッグ機能を掛けたり、同じオーバーロードから収集した統計に基づいてアプリ全体を大幅に改善したりするのに便利だからです。
個々の型にもカスタム アロケーターを使用しています。多くの場合、カスタム アロケータを提供することで得られるスピードアップや機能は、たとえば STL データ構造の単一の使用ポイントに提供することで得られるものであり、グローバル オーバーロードから得られる一般的なスピードアップをはるかに超えています。
C/C++ 用に出回っているアロケーターとデバッグ システムのいくつかを調べてみると、次のアイデアやその他のアイデアがすぐに思いつくでしょう。
(古いが影響力のある本の 1 つは、 Writing Solid Codeで、C でカスタム アロケーターを提供する理由の多くが説明されており、そのほとんどは今でも非常に関連性があります。)
これらの優れたツールのいずれかを使用できる場合は、自分で作成するよりも使用したいと思うでしょう。
それがより速く、より簡単で、ビジネス/法的な面倒が少ない、プラットフォームでまだ何も利用できない、またはより有益な状況があります: グローバルなオーバーロードを掘り下げて記述します。