3

Ubuntu で c++ を実行しています。

configuration.h ファイルには、これがあります (グローバル):

static const string APP_CONFIG_FILE_NAME = "cfg";

私のconfiguration.cpp(ちなみにシングルトンであるため、負荷設定はConfigurationのコンストラクターによって呼び出されます)で、私はこれを行います:

void Configuration::loadConfiguration() {
    cout<< "config file name "  << APP_CONFIG_FILE_NAME.data();
        load();
}

ロード構成は別のグローバルから呼び出されます: (これが失敗の重要なポイントです)

Timer t(Configuration::Instance()->timeout);

コスト文字列が初期化されていない (空) ことがわかります。文字列を char* に置き換えると、予想される順序で初期化されます。

ただし、別のプログラムでは、同じクラスの構成が機能するため、問題がわかりません。

別の質問がありますが、グローバルではないため、同じではありません。

4

2 に答える 2

9

もちろん初期化されます。ただし、初期化したくない/期待しない順序で初期化されている可能性があります。

具体的には、別のグローバルの構築中に使用するため、使用するまでに構築されていない可能性があります。

残念ながら、グローバル データの初期化順序を移植可能に指定する良い方法はありません。複数のファイル間の初期化順序は標準では定義されていませんが、ツールチェーンで指定されている可能性があります。したがって、別のツールチェーンを使用してコンパイルまたはビルドの順序を変更すると、異なる初期化順序になる可能性があります。詳細については、「静的初期化順序の大失敗」を検索してください。

この問題を回避する 1 つの方法は、静的データを関数で宣言することです。

const std::string& AppConfigFileName() {
  static const std::string name("cfg");
  return name;
}

ただし...これが静的でなければならない理由がわかりません(上記の関数では、値で返すことができます-静的は必要ありません)。さらに、構成ローダーでC文字列として扱うだけなので、これがプレーンなC文字列ではない理由がわかりません。

于 2012-08-21T11:18:19.483 に答える
2

重要な問題は、がいつConfiguration::loadConfiguration呼び出されるかです。変換ユニット間の初期化の順序は定義されていないためConfiguration::loadConfiguration、別の変換ユニットの静的オブジェクトのコンストラクターからが呼び出された場合、変数が作成されていない可能性があります。この特定のケースでは、最も簡単な解決策は、タイプをchar const[];に変更することです。これにより、動的初期化の前に発生する静的初期化が可能になります。(重要なコンストラクターを含む初期化は動的です。)より一般的には、文字列にシングルトンパターンを使用できます。

他のいくつかの点も言及する価値があります:

  • staticヘッダーファイルでオブジェクトのインスタンスを宣言しました。これは、ヘッダーファイルを含むすべての変換ユニットがオブジェクトの個別のインスタンスを持つことを意味します。これはおそらく良い考えではありません。

  • 出力しますAPP_CONFIG_FILE_NAME.data()。これは単にstd::stringオブジェクト内のデータであり、終了することは保証されていませ'\0'ん 。'\0'終了文字列 が必要な場合は、を使用する必要がありますstd::string::c_str()。(ただし、この場合は、出力するだけです std::string。関数を呼び出す必要はありません。)

于 2012-08-21T11:33:57.993 に答える