#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; }