30

C++ でいくつかのクラスをファクトリに登録するプロセスを容易にするために、静的初期化を使用しています。残念ながら、コンパイラーは、コンストラクターで有用な作業を行うための「未使用」オブジェクトを最適化していると思います。グローバル変数を最適化しないようにコンパイラに指示する方法はありますか?

class SomeClass {
    public:
        SomeClass() {
            /* do something useful */
        }
};

SomeClass instance;

SomeClass のコンストラクターのブレークポイントがヒットしません。私の実際のコードでは、SomeClass はヘッダー ファイルにあり、インスタンスはソース ファイルにあり、多かれ少なかれ単独です。

編集: KJAWolf が推測したように、このコードは実際には実行可能ファイルではなく、静的ライブラリにコンパイルされます。その目的は、静的ライブラリによって提供されるいくつかの型を、型とその作成者の静的リストに登録して、ファクトリが構築時に読み取るようにすることです。これらの型は lib で提供されるため、このコードを実行可能ファイルに追加することは望ましくありません。

また、他の既存のコードを含む別のソース ファイルにコードを移動すると、問題なく動作することがわかりました。これらのグローバル オブジェクトだけで構成されたファイルがあることが問題の原因のようです。その翻訳単位が完全に無視されたかのようです。

4

9 に答える 9

44

コンパイラは、グローバルオブジェクトを最適化することはできません。
一度も使用されていなくても。

あなたのコードで何か他のことが起こっています。
これで、グローバルオブジェクトを使用して静的ライブラリを構築し、そのグローバルオブジェクトが実行可能ファイルから参照されていない場合、リンカーによって実行可能ファイルにプルされません。

于 2009-08-04T19:47:19.797 に答える
5

コンパイラは、そのようなグローバルを最適化してはなりません。最適化すると、単に壊れてしまいます。

于 2009-08-04T19:44:05.717 に答える
2

完全な静的ライブラリを構築する前に、それらを部分的にリンクすることにより、1 つのオブジェクト (タイプのリスト) が他のオブジェクトをプルするように強制できます。

GNU リンカーを使用する場合:

ld -Ur -o TypeBundle.o type1.o type2.o type3.o static_list.o
ld -static -o MyStaticLib.a type_bundle.o other_object.o another_object.o ...

したがって、静的リストがライブラリを使用するコードによって参照されるときは常に、完全な「TypeBundle.o」オブジェクトが結果のバイナリ (type1.o、type2.o、および type3.o を含む) にリンクされます。

その際、マニュアルの「-Ur」の意味を確認してください。

于 2016-08-29T16:46:09.667 に答える
1

Arthur Ulfeldt から構築するために、volatile は、この変数がコンパイラの知識の範囲外で変更される可能性があることをコンパイラに伝えます。デバッガーがブレークポイントを設定できるようにするステートメントを配置するために使用しました。また、環境に基づいて変化するハードウェア レジスタや、特別なシーケンスが必要なハードウェア レジスタにも役立ちます。すなわち、シリアル ポート受信レジスタと特定のウォッチドッグ レジスタです。

于 2009-08-04T19:55:10.280 に答える
1

あなたが使用できる

#pragma オプティマイズ オフ
int globalVar
#pragma optimize on

しかし、それが Visual Studio ( http://msdn.microsoft.com/en-us/library/chh3fb0k(VS.80).aspx ) でのみ機能するかどうかはわかりません。

特にデバッグしている場合は、コンパイラにまったく最適化しないように指示することもできます...

于 2009-08-04T19:57:24.177 に答える
0

gdb で gcc を使用していますか? 過去に、gdb がコンストラクターにブレークポイントを正確に設定できないという問題がありました。

また、コンパイラがクラス定義でメソッドをインライン化できるようにする最適化レベルを使用していますか。

于 2009-08-04T20:02:25.430 に答える
0

VS2008でも同じセットアップと問題があります。dllexportクラスを宣言すると、最適化されないことがわかりました。

class __declspec( dllexport ) Cxxx
{
.
}

ただし、このクラスで使用されるすべてのクラスを dllexport としても宣言する必要があるため、私の場合は多くの警告が生成されます。

すべての最適化は (デバッグ モードで) オフになっていますが、これは最適化されています。また、揮発性/プラグマ最適化オフ。このクラス (同じ cpp ファイル内) で作成されたグローバル変数などでは機能しません。

dllexport が機能するには、少なくともこれらのクラスのヘッダー ファイルを exe から他の cpp ファイルに含める必要があることがわかりました。したがって、唯一のオプションは、クラスごとにいくつかの静的メンバーへの呼び出しを含むファイルを追加し、このファイルをこれらのクラスを使用するすべてのプロジェクトに追加することです。

于 2011-02-23T09:46:01.680 に答える
0

リンクするときは -whole-archive を使用する必要があります。ここで答えを見てください:

ld リンカーの質問: --whole-archive オプション

于 2011-04-14T16:13:35.310 に答える
-1

キーワード volatile を使用するのはどうですか? コンパイラが過度に最適化するのを防ぎます。

于 2009-08-09T01:43:49.097 に答える