В чем разница между MinGW SEH и MinGW SJLJ?

Я только начинаю изучать C и сейчас устанавливаю QT x64 (форма здесь: http://tver-soft.org/qt64). У меня есть два варианта установки: MinGW 4.9.2 SEH или MinGW 4.9.2 SJLJ.
Вопрос: что лучше установить и почему?

Я читаю В чем разница между Sjlj против карлика против Seh? и https://wiki.qt.io/MinGW-64-bit#Exception_handling:_SJLJ.2C_DWARF.2C_and_SEH, но ничего не понимаю (плохо знакомы с языками C и компилятора).

Ответ 1

SJLJ и SEH - две разные системы обработки исключений.

Что касается конкретных различий, ресурсы, которые вы уже видели, охватывают все.

Однако, какой из них лучше установить, используйте SJLJ, если вы не знаете, что вам нужен SEH.

Обновление 2019: в современных системах нет причин использовать SJLJ, поэтому совет, приведенный выше, вероятно, следует перевернуть. SEH более распространен сейчас. В конечном счете, это не имеет большого значения, так как легко переключаться между ними.

SJLJ

SJLJ более широко поддерживается в разных архитектурах и является более надежным. Кроме того, исключения SJLJ могут создаваться через библиотеки, использующие другие системы обработки исключений, включая библиотеки C. Тем не менее, он имеет снижение производительности.

SEH

SEH гораздо более эффективен (без снижения производительности), но, к сожалению, не очень хорошо поддерживается. Исключения SEH приведут к возникновению плохих вещей, если их выбросить через библиотеки, которые также не используют SEH.

Что касается вашего кода, то никаких реальных отличий нет. Вы всегда можете переключить компиляторы позже, если вам нужно.

Ответ 2

Я обнаружил одно различие между обработкой исключений SJLJ и SEH в обработчиках сигналов MinGW-w64: C, заданных функцией signal(), не работает в версии SJLJ, как только по крайней мере один блок try {} запускается во время выполнения. Поскольку этот вопрос нигде не описывается, я помещаю его здесь для записи.

В этом примере демонстрируется следующий пример (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 он ведет себя так, как ожидалось (обработчик сигнала вызывается).

У меня нет четкого представления о том, почему эта проблема возникает, поэтому будем благодарны, если кто-нибудь сможет дать объяснение.