私はこの問題と2日間戦っていました。回避策はありますが、さらに何が起こるかを理解したいです。それでは始めましょう。エラーメッセージを文字配列へのポインタとして保持する非常にプリミティブな例外クラスがあります(std::stringの利益について知っています)。「3つのルール」を知っているので、次のようになります。
globalexceptions.hpp
class FatalError {
public:
const char* errorMessage;
/* WARNING:
* "Rule of three". You see it below.
*/
FatalError(const char* pErrorMessage);
FatalError(const FatalError& rhs);
FatalError& operator=(const FatalError& rhs);
~FatalError();
};
グローバル例外.cpp
FatalError::FatalError(const char *pErrorMessage):
errorMessage(pErrorMessage)
{}
FatalError::FatalError(const FatalError& rhs){
char* buf = new char[strlen(rhs.errorMessage)+1];
strcpy(buf, rhs.errorMessage);
errorMessage = buf;
}
FatalError& FatalError::operator =(const FatalError& rhs){
if (this == &rhs)
return *this;
delete[] errorMessage;
char* buf = new char[strlen(rhs.errorMessage)+1];
strcpy(buf,rhs.errorMessage);
errorMessage = buf;
return *this;
}
FatalError::~FatalError(){
delete[] errorMessage;
}
しかし、投げるとき:
int Config::readConfig(int argc_p, char *argv_p[])
{
if ( argc_p != 2 )
{
throw FatalError ("Sick usage. Try: <file.ini>\n");
}
「SIGABRT」を取得します。
いくつかの valgrind 分析:
Invalid free() / delete / delete[] / realloc()
in FatalError::~FatalError() in globalexceptions.cpp:26
Address 0x413980 is not stack'd, malloc'd or (recently) free'd 1: operator delete[](void*) in /tmp/buildd/valgrind-3.7.0/coregrind/m_replacemalloc/vg_replace_malloc.c:490
2: FatalError::~FatalError() in <a href="file:///home/gumba/Projects/cpp/backup_helper/backup_helper-build-desktop-Qt_4_8_2_in_PATH__System__Debug/../backup_helper/globalexceptions.cpp:26" >globalexceptions.cpp:26</a>
3: /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17
4: main in <a href="file:///home/gumba/Projects/cpp/backup_helper/backup_helper-build-desktop-Qt_4_8_2_in_PATH__System__Debug/../backup_helper/main.cpp:35" >main.cpp:35</a>
私はいくつかの調査を行い、次の情報とアドバイスを見つけました。
- ( OK: 参照によるキャッチ) 「技術的には、参照によって例外をキャッチした場合でも、コンパイラは値渡しを使用します。これは、キャッチが呼び出し元に制御を返さないためです。上"
- ( OK: コピー コンストラクターを使用) 「スローされるオブジェクトには、パブリックにアクセス可能なコピー コンストラクターが必要です。コンパイラーは、スローされたオブジェクトを何度でもコピーするコードを生成できます (ゼロを含む)。ただし、コンパイラーが実際にコピーしない場合でも、例外クラスのコピー コンストラクターが存在し、アクセス可能であることを確認する必要があります。」
GDB によると、コピー コンストラクターは呼び出されません。SIGABRT はdelete[] errorMessageで発生します。理由がわかりません。errorMessage は適切に初期化されているようです。
SIGABRTの理由は何ですか?
ありがとう!