странные проблемы с исключениями C с mingw

#c #exception-handling #mingw32

#c #исключение #mingw32

Вопрос:

Я столкнулся со странными проблемами с исключениями, использующими mingw, и мне удалось сократить их до следующего примера:

 #include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;

void test(int a) {
    if (a < 0) {
        throw std::ios_base::failure("a < 0");
    }
}
void test_file(std::string const amp; fName)
{
    std::ifstream inF(fName.c_str(), std::fstream::in);
    if (!inF) {
        cout << "file error -> throwing exception" << endl;
        throw ios_base::failure("could not open input file '"   fName   "'");
    }
}

int main()
{
    try { test(-5); }
    catch(std::exceptionamp; e) {
        cerr << "Exception caught: " << e.what() << " .. continue anyway" <<endl;
    }

    try { test_file("file-that-does-not-exist"); }
    catch(std::exceptionamp; e) {
        cerr << "Exception caught: " << e.what() << endl;
        exit(EXIT_FAILURE);
    }
    return EXIT_SUCCESS;
}
  

Первое исключение перехвачено, а второе — нет, поэтому я получаю сообщение об ошибке Windows, информирующее меня о том, что мое приложение перестало работать 🙁
Полный вывод командной строки:

Поймано исключение: a < 0 .. продолжить в любом случае
ошибка файла -> выбрасывание исключения

Это приложение запросило среду выполнения завершить его необычным способом. Пожалуйста, свяжитесь со службой поддержки приложения для получения дополнительной информации.

То же самое происходит и с другими исключениями (например, std::runtime_error ).

Я делаю что-то не так, или проблема где-то в другом месте?

Информация о системе: Windows 7 x64, последняя версия mingw32 (переустановлена вчера с помощью mingw-get из mingw.org ).

Заранее большое спасибо.
Михал

Комментарии:

1. Подробнее: я обнаружил, что в моей IDE (Code::Blocks) используется опция компоновщика «-static-libgcc». Когда я удаляю его, он работает так, как ожидалось. Для меня это действительно похоже на ошибку.. Есть ли какая-либо причина (не) использовать эту опцию вообще?

2. Обновление : код работает, если он скомпилирован как g -static-libgcc -static-libstdc main.cpp или просто g main.cpp . Единственная версия, которая не работает, — это g -static-libgcc main.cpp —, которая настроена в моей IDE 😉 Это ошибка? И, что более важно, есть ли какие-либо причины для выбора одного из первых двух над другим?

3. @ Michal: правдоподобная ошибка. Тогда это была бы ошибка в Code::Blocks (неспособность определить специфические для c флаги компилятора).

4. @ sehe: вы хотите сказать, что -static-libgcc это не должно работать без -static-libstdc кода на C ? Я этого не знал (очевидно).

Ответ №1:

FWIW, на XP SP3 с MinGW:

 Using built-in specs.
Target: mingw32
Configured with: ../gcc-4.4.0/configure --prefix=/mingw --build=mingw32 --enable-languages=c,ada,c  ,fortran,objc,obj-c   --disable-nls --disable-win32-registry --disable-werror --enable-threads --disable-symvers --enable-cxx-flags='-fno-function-sections -fno-data-sections' --enable-fully-dynamic-string --enable-libgomp --enable-version-specific-runtime-libs --enable-sjlj-exceptions --with-pkgversion='TDM-1 mingw32' --with-bugurl=http://www.tdragon.net/recentgcc/bugs.php
Thread model: win32
gcc version 4.4.0 (TDM-1 mingw32)
  

Приводит к a.exe:

     ntdll.dll => /cygdrive/c/WINDOWS/system32/ntdll.dll (0x7c900000)
    kernel32.dll => /cygdrive/c/WINDOWS/system32/kernel32.dll (0x7c800000)
    msvcrt.dll => /cygdrive/c/WINDOWS/system32/msvcrt.dll (0x77c10000)
  

Вывод

 Exception caught: a < 0 .. continue anyway
file error -> throwing exception
Exception caught: could not open input file 'file-that-does-not-exist'
  

Итак, это мягкое доказательство, указывающее в направлении

  • несовместимость библиотек
  • различия в среде
  • ошибка (?) в вашей версии MinGW

Комментарии:

1. Какая версия исключения TDM — SJLJ или DW2 разматывается? Насколько я знаю, «официальный» mingw использует DW2 (начиная с gcc 4.4), в то время как TDM предлагает оба варианта и рекомендует SJLJ в качестве выбора по умолчанию..

2. SJLJ (как показано в ответе --enable-sjlj-exceptions , но также проверено с objdump.exe a.exe -s -x| egrep -i 'tdm|sjlj|dwarf|dw2' помощью)

3. Просто из интереса — не могли бы вы попробовать скомпилировать его с -static-libgcc ? (Причины см. В моем комментарии выше.)

4. Только что сделал, никаких проблем для меня. ОДНАКО: при использовании cygwin g с -static-libgcc ним происходит сбой (он работает нормально без флага) (но вы получите совершенно другой результат ldd .) Вы путаете установки компилятора?

5. У меня установлен только один компилятор, gcc, который поставляется с mingw (без cygwin) — так что нет, я не смешиваю компиляторы. Тем не менее, я нашел возможную причину ошибки, см. Мое Обновление исходного сообщения выше.

Ответ №2:

Нет, я не думаю, что вы делаете что-то не так, это довольно стандартно и довольно хорошо работает под Linux.

Я бы предложил задать запрос людям MinGW. Даже если это не ошибка, они должны быть в состоянии сообщить вам, что происходит.

Ответ №3:

У меня также возникла проблема с этим (6 лет спустя), за исключением того, что мой найден с MSYS2, cmake / ninja / mingw32 в Windows 7:

CMakeLists.txt:

 cmake_minimum_required(VERSION 3.6)
project(FailedExceptions )
add_executable(FailedExceptions  main.cpp foo.c)
  

Вывод:

 $ cmake .. -GNinja
-- The C compiler identification is GNU 7.2.0
-- The CXX compiler identification is GNU 7.2.0
-- Check for working C compiler: C:/msys64/mingw32/bin/cc.exe -- works
-- Check for working CXX compiler: C:/msys64/mingw32/bin/c  .exe -- works
-- Configuring done
-- Generating done
-- Build files have been written to: C:/msys64/home/sferguson/src/vis/build

$ ninja -v
[1/3] C:msys64mingw32bincc.exe    -MD -MT CMakeFiles/FailedExceptions.dir/PortDescription.c.obj -MF CMakeFilesFailedExceptions.dirPortDescription.c.obj.d -o CMakeFiles/FailedExceptions.dir/PortDescription.c.obj   -c ../PortDescription.c
[2/3] C:msys64mingw32binc  .exe     -MD -MT CMakeFiles/FailedExceptions.dir/main.cpp.obj -MF CMakeFilesFailedExceptions.dirmain.cpp.obj.d -o CMakeFiles/FailedExceptions.dir/main.cpp.obj -c ../main.cpp
[3/3] cmd.exe /C "cd . amp;amp; C:msys64mingw32binc  .exe    CMakeFiles/FailedExceptions.dir/main.cpp.obj CMakeFiles/FailedExceptions.dir/PortDescription.c.obj  -o FailedExceptions.exe -Wl,--major-image-version,0,--minor-image-version,0  -lgcc_eh -lgcc_eh -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 amp;amp; cd ."

$ ./FailedExceptions.exe
Exception caught: a < 0: iostream error
file error -> throwing exception

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
  

Единственная загвоздка в том, что мне также нужно связать некоторый (любой) файл c, даже если я ничего не использую, что он предоставляет. В этом случае я сделал это с foo.c :

 int foo() { return 0; }