私はCを学び始め、今QT x64をインストールしています(ここにフォーム: http://tver-soft.org/qt64 )。インストールには2つのオプションがあります:MinGW 4.9.2 SEH
またはMinGW 4.9.2 SJLJ
。
質問:どちらをインストールするのが良いのですか、それはなぜですか?
読んだ sjljとdwarfとsehの違いは何ですか? と https://wiki.qt.io/MinGW-64-bit#Exception_handling:_SJLJ .2C_DWARF.2C_and_SEH しかし、何も理解していません(Cおよびコンパイラ言語の新機能)。
SJLJとSEHは、2つの異なる例外処理システムです。
特定の違いについては、すでに見たリソースがすべてをカバーしています。
ただし、どちらがbetterのインストールに適しているかについては、 sEHが必要であることを知らない限り、[〜#〜] sjlj [〜#〜]を使用してください。
2019 Update:最近のシステムでは、SJLJを使用する理由はないので、上記のアドバイスはおそらく反転させる必要があります。 SEHはより一般的になりました。ただし、この2つを簡単に切り替えることができるので、結局は問題ではありません。
SJLJは、アーキテクチャ全体でより広くサポートされており、より堅牢です。また、SJLJ例外は、Cライブラリを含む他の例外処理システムを使用するthroughライブラリをスローできます。ただし、パフォーマンスが低下します。
SEHの方がはるかに効率的ですが(パフォーマンスが低下することはありません)、残念ながら十分にサポートされていません。 SEH例外を使用すると、SEHを使用しないライブラリを介してスローされると、問題が発生します。
コードに関する限り、実際の違いはありません。必要に応じて、後でいつでもコンパイラを切り替えることができます。
MinGW-w64でのSJLJとSEHの例外処理の1つの違いを発見しました。signal()関数によって設定されたCシグナルハンドラーは、実行時に少なくとも1つのtry {}ブロックが実行されるとすぐにSJLJバージョンで機能しなくなります。この問題はどこにも説明されていないようなので、ここでは記録のためにここに置いておきます。
次の例(test_signals.cpp)はこれを示しています。
// This sample demonstrates how try {} block disables handler set by signal()
// on MinGW-w64 with GCC SJLJ build
#include <signal.h>
#include <iostream>
int izero = 0;
static void SIGWntHandler (int signum)//sub_code)
{
std::cout << "In signal handler, signum = " << signum << std::endl;
std::cout << "Now exiting..." << std::endl;
std::exit(1);
}
int main (void)
{
std::cout << "Entered main(), arming signal handler..." << std::endl;
if (signal (SIGSEGV, (void(*)(int))SIGWntHandler) == SIG_ERR)
std::cout << "signal(OSD::SetSignal) error\n";
if (signal (SIGFPE, (void(*)(int))SIGWntHandler) == SIG_ERR)
std::cout << "signal(OSD::SetSignal) error\n";
if (signal (SIGILL, (void(*)(int))SIGWntHandler) == SIG_ERR)
std::cout << "signal(OSD::SetSignal) error\n";
// this try block disables signal handler...
try { std::cout << "In try block" << std::endl; } catch(char*) {}
std::cout << "Doing bad things to cause signal..." << std::endl;
izero = 1 / izero; // cause integer division by zero
char* ptrnull = 0;
ptrnull[0] = '\0'; // cause access violation
std::cout << "We are too lucky..." << std::endl;
return 0;
}
ビルド:
g++ test_signals.cpp -o test_signals.exe
予想される出力は次のとおりです。
Entered main(), arming signal handler...
In try block
Doing bad things to cause signal...
In signal handler, signum = 8
Now exiting...
MigGW-w64 SJLJバリアントでビルドしたときの実際の出力は次のとおりです。
Entered main(), arming signal handler...
In try block
Doing bad things to cause signal...
アプリケーションは、少し遅れてサイレントに終了します。つまり、シグナルハンドラは呼び出されません。 try {}ブロックがコメント化されている場合、シグナルハンドラーは適切に呼び出されます。
MinGW-w64 SEHバリアントを使用すると、期待どおりに動作します(シグナルハンドラーが呼び出されます)。
なぜこの問題が発生するのかはっきりしないので、誰かが説明してくれるとありがたいです。