longjmp や exit のようなルーチンは、C++ プログラムでは使用できません。
C++ オブジェクト・セマンティクスは、ブロックの最後まで実行されたか、サブルーチンからリターンされたか、または例外がスローされたかに関係なく、スコープの終了時にローカル・オブジェクトを破棄します。longjmp のような一部の C ライブラリーは、一度にスタックの複数のレイヤーをアンワインドすることができません。これらのルーチンでは、C++ オブジェクト・セマンティクスが順守されません。つまり、中間のスタックフレームが 1 つずつ破棄されず、ローカル変数も破棄されません。オブジェクトを破棄する際には、常にデストラクターが呼び出されるという C++ の規則に違反します。そのため、このようなルーチンは C++ プログラムでは使用できません。
プログラムの既存のすべての呼び出しを検証した結果、破棄する必要のあるローカル・オブジェクトのインスタンスをすべての親が保持しているため、特定の exit や longjmp の呼び出しが安全であることもあります。そのような場合であっても、一般的にこの使用方法が安全でないことには変わりなく、将来、警告を出力せずに安全ではない状態を引き起こす新しい呼び出しが追加される可能性があります。そのため、実際に問題が発生していなくても、エラーを引き起こしやすいため、排除する必要があります。
問題の使用方法は、C++ 例外として記録することができます。つまり、"exit" を呼び出す代わりに、メインルーチンで処理される例外をスローできます。setjmp の呼び出しの代わりに catch 節を使用して、longjmp の呼び出しの代わりに catch 節で検出される例外をスローします。
ID |
問題箇所 |
説明 |
---|---|---|
1 |
呼び出し位置 |
演算子が使用された場所 |
#include <string.h> #include <stdlib.h> #include <iostream> using namespace std; // Class accumulates a string that gets // printed when the instance is destroyed class StringHolder { private: char *stringToPrint; public: explicit StringHolder(char * string) { size_t size = strlen(string) + 1; stringToPrint = (char *)malloc(size); strcpy_s(stringToPrint, size, string); } ~StringHolder() { cout << stringToPrint; free(stringToPrint); } // copy constructor StringHolder::StringHolder(const StringHolder & source) { size_t size = strlen(source.stringToPrint) + 1; stringToPrint = (char *)malloc(size); strcpy_s(stringToPrint, size, source.stringToPrint); } // assignment operator StringHolder& StringHolder::operator=(const StringHolder & source) { free(stringToPrint); size_t size = strlen(source.stringToPrint) + 1; stringToPrint = (char *)malloc(size); strcpy_s(stringToPrint, size, source.stringToPrint); return *this; } }; void f(int n) { if (n != 0) { StringHolder IDontGetDestroyed("Arguments present"); exit(0); } // Object IDontGetDestroyed never gets torn down // because of call to exit, so nothing gets printed } int main(int argc, char **argv) { f(argc); return 0; }
© 2010 Intel Corporation. 無断での引用、転載を禁じます。