プロジェクトのために C++ を学ぼうとしていますが、文字列の連結に少し問題があります。私のアプリケーションは、アプリケーション自体と静的にリンクされたライブラリ プロジェクトで構成されています。ライブラリでは、ファイル システム上のパスを表す型を定義し、std::string パス リテラルのラッパーとして機能します。親フォルダーのパスをファイル/フォルダー自体の (ユーザーが指定した) 名前と連結し、必要に応じてパス区切り記号を追加する関数を定義しました。関数コードは次のようになります。
std::string normalize(std::string parentPath, const std::string& name) {
if (name.empty()) {
return parentPath;
} else {
parentPath.reserve(parentPath.length()+name.length()+1);
if (*name.begin() != Path::SEGMENT_SEPARATOR) {
parentPath.append(1,Path::SEGMENT_SEPARATOR);
}
if(*name.rbegin() != Path::SEGMENT_SEPARATOR){
parentPath.append(name);
}else{
parentPath.append(name.begin(), --name.end());
}
return parentPath;
}
}
(Path::SEGMENT_SEPARATOR は const char '/' です)
問題はこれです: string::append へのすべての呼び出しは何もしないようです。関数を gdb でデバッグしましたが、parentPath の内容は変わりません。ユーザー入力をチェックして、入力に「/0」またはその他の無効な文字 (「名前」) がないか調べましたが、問題は見つかりませんでした。
まったく同じ関数を (ライブラリ プロジェクトから) アプリケーション プロジェクトに移動したところ、(同じ入力で) 期待どおりに機能しました。
両方のプロジェクトは、同じツールセット (GCC 4.8.1 および C++11 方言を使用) と同じコンパイラ パラメーター (すべての警告がオンで、コードで警告は受信されません) を使用してコンパイルされます。この方法で string::append を壊す可能性のあるコードはありますか?
編集:関数は次から呼び出されます:
Path::Path(const Path& parent, const std::string& name) : path_(normalize(parent.path_, name)) { }
Path::Path(const Path& parent, const char* name) : Path(parent, std::string(name)) {}
次に、from(ヘッダーファイル)と呼ばれます:
extern const IO::Path CONFIG_PATH;
extern const IO::Path LANGUAGES_PATH;
cpp ファイルでの定義:
const IO::Path Game::CONFIG_PATH{"conf"};
const IO::Path Game::LOG_PATH{CONFIG_PATH,"log"};
LOG_PATH オブジェクトを調べると、その「path_」メンバー値が、予想どおり「conf/log」ではなく「conf」として表示されます。CONFIG_PATH が LOG_PATH の前に初期化されていることを確認できますか? これが問題になる可能性はありますか?
編集: 標準を読みましたが、グローバルの初期化順序に依存できないようです。これは、CONFIG_PATH と LOG_PATH の宣言が明らかにエラーであることを意味し、おそらく次のような関数呼び出しにラップする必要があります。
const IO::Path &getConfigPath(){
static IO::Path config{"conf"};
return config;
};
これが、文字列の追加が失敗する理由ですか?