LINUX.ORG.RU

[C++, CMake, MinGW, кросскомпиляция] try ... catch не ловит исключения.


0

1

Здравствуйте!

Программа собирается с помощью CMake. Одна из целевых ОС - Windows. Реализована следующая фабрика:

Base* load(const char* filename) {
	try {return new Derived1(filename);} catch (...) {}
	try {return new Derived2(filename);} catch (...) {}
	try {return new Derived3(filename);} catch (...) {}
	try {return new Derived4(filename);} catch (...) {}
	try {return new Derived5(filename);} catch (...) {}
	try {return new Derived6(filename);} catch (...) {}
	throw std::runtime_error(std::string("Couldn't load file: ") + filename);
}

При кросскомпиляции с помощью MinGW возникает следующая проблема: исключение, поднятое в конструкторе Derived1 не ловится try...catch. При сборке для linux всё работает. Проблема присутствует при всех вариантах CMAKE_BUILD_TYPE. В качестве дополнительных ключей компилятору задавались только: -Wall -Wextra

Debian Oldstable, софт из оф. репозитория.



Последнее исправление: SSN (всего исправлений: 1)
Ответ на: комментарий от kiverattes

>Человек смотрит на возможность инструмента и использовать любую увиденную возможность - его дело, ругаться на забивание гвоздей микроскопом - совок.

У С++ есть такая особенность что в нем надо знать кучу практик кодирования для решения типовых мелких проблем и придерживаться только их. Исключение как нелокальный break или нелокальный goto в такие практики не входят.

Absurd ★★★
()
Ответ на: комментарий от Absurd

Я перед собой в лице данного треда вижу такую практику.

kiverattes ★☆
()
Ответ на: комментарий от Begemoth

Только если одно и другое - экземпляры классов или ссылки на них.

Посыпаю голову пеплом, legolegs всё правильно заметил, оператор || возвращает bool. Имелось в виду что-то вроде:

inline Base & operator|( Base & first, Base & second )
{
    return &first ? first : second;
}

Base & value =
    *Deriver1::create(filename) |
    *Deriver2::create(filename) |
    ...
    *Deriver6::create(filename);
return &value;

Проверил в VC2010, работает нормально. Хотя да, выглядит жутковато.

Dendy ★★★★★
()
Ответ на: комментарий от Dendy

Проверил в VC2010, работает нормально. Хотя да, выглядит жутковато.

Как проверял? Дело в том, что переопределённые операторы всегда вычисляют все свои аргументы (т.к. это просто замаскированный вызов функции), поэтому если не нулевое значение возвращает несколько функций DeriverN::create то ты получишь утечки памяти. Как вариант DeriverN::create может возвращать отложенное вычисление, которое уже будет создавать необходимый объект, и переопределить operator|| для этих отложенных вычислений.

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

Да, всё верно, будет утечка. Вобщем, если что-то выглядит как хак - жди беды (-:

Base * base = 0;
(base = Deriver1::create(filename)) ||
(base = Deriver2::create(filename)) ||
...
(base = Deriver6::create(filename));
return base;
Dendy ★★★★★
()
Ответ на: комментарий от Reset

> Ловить надо только те exception'ы которые ты ожидаешь, в остальных случаях надо падать.

То есть, если у меня программка, и к ней кучка плагинов в виде .so, моя оболочка должна гордо умереть, когда в одном из плагинов непредусмотренная ошибка?

Нет уж, нафиг-нафиг.

hobbit ★★★★★
()
Ответ на: комментарий от hobbit

гораздо лучше упасть, чем несколько дней разбираться почему при загрузке плагина X у тебя в программе периодически отваливаются фичи Y или вообще программа начинает вести себя неадекватно. Если нужна надежность, то делай плагины-процессы и связывай их с основной программой pipe'ом. Иначе никак.

Reset ★★★★★
()
Ответ на: комментарий от Reset

> чем несколько дней разбираться

Почему? Если я обработаю этот самый ..., я вставлю туда сообщение: «Неопознанная ошибка в расширении XXX». Таким образом, я сразу сужаю поле для поисков.

hobbit ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.