Параметр командной строки для gcc для указания любого программного исключения может оставить функции, объявленные с помощью throw () - PullRequest
1 голос
/ 07 декабря 2011

Я пишу программу с использованием gcc на c ++.На декабрьВ-пятых, я отправил вопрос из-за странной проблемы (https://stackoverflow.com/a/8392854/837803).Когда программная исключительная ситуация оставляет функцию, объявленную без спецификаций throw, как это:

int foo();

или это:

int foo() throw();

сгенерированный gcc код завершится сбоем.

Я хочу сказать gcc, что любое программное исключение может оставить любую функцию, которую я напишу.Я думаю, что это что-то вроде:

int foo() throw(...);

НО: я не хочу писать throw (...) во всех спецификациях функций.Я понимаю, что размер моей программы будет больше, но это не проблема для этого случая.Кроме того, я прочитал, что поведение gcc, которое я предлагаю, является нарушением ANSI.Но это тоже не проблема.

Среди многих, многих, многих параметров командной строки gcc, должен быть один, который я ищу, но я еще не нашел его.

Какой вариант я ищу?

Ответы [ 3 ]

2 голосов
/ 07 декабря 2011

Я возражаю против этого:

сгенерированный gcc код завершится сбоем.

Это просто неправильно .

Функция, объявленная так:

 void func1();

Если вы сгенерируете исключение, это приведет к тому, что стек раскрутится до подходящего улова. Если нет подходящего перехвата, из которого выходит программа (в этом случае стек раскручивается, это определяется реализацией (таким образом, перехватывает все в main)).

Функция, объявленная так:

void func2() throw(); // ie no throw.

Если исключение ускользает от этой функции, то вызывается непредвиденный (). Действие по умолчанию для непредвиденных событий - это вызов abort (), который заставляет программу завершать работу (Примечание: вы можете заменить непредвиденное на пользовательскую функцию, но она должна либо выйти, либо выдать альтернативное исключение, которое может передать спецификацию throw (в этом случае это невозможно)).

Требуемое поведение является поведением по умолчанию (без спецификации броска). Спецификации броска были экспериментом, который потерпел неудачу и поэтому был признан устаревшим. Вы не должны использовать их в любом случае (не считая броска).

Таким образом, вы можете получить нормальный рабочий код с исключениями, если вы определите свои функции следующим образом:

void func3(); // Exceptions work fine.

Но лучше всего ставить улов в main ()

int main()
{
    try
    {
        // DoWork
    }
    catch(std::exception const& e)  // We can print a good error message with these
    {
        log(e.what()); 
        throw;                     // Not much you can do so re-throw for the OS.
    }
    catch(...)                     // Catch all other exceptions.
    {
        log("Unknown Exception");
        throw;                     // Not much you can do so re-throw for the OS.
    }
    // Catching forces the stack to unwind all the way to main()
    // Otherwise it is implementation defined whether it unwinds.
}
0 голосов
/ 07 декабря 2011

В следующем предполагается, что вы выдаваете исключение типа , описанного в этом вопросе .

Ваш тип исключения не работает.

В throw_exception мы имеем эту строку:

text l_message;

Я не знаю, что такое text, но я предполагаю, что это строковый класс. Я также предположу, что test::_char - это просто причудливый способ сказать char.

Итак, у нас есть объект стека l_message, который имеет тип text. Позже у нас есть эта строка:

throw exc((const text::_char *)l_message);

Поскольку вы не соизволили нам дать определение text, опять же, я должен сделать предположение. Я предполагаю, что для text определен operator text::_char*, определенный для него, который возвращает указатель на строку в стиле C, представляющую сохраненные строковые данные, которая заканчивается на NULL.

Только есть одна проблема: этот указатель принадлежит l_message.

В момент, когда l_message падает со стека, указатель, возвращаемый l_message, исчезает. Это было бы хорошо ... если бы класс exc фактически скопировал эту строку во внутренний буфер. Но это не так. Он просто хранит указатель.

Указатель, который больше не указывает на действительную память. Это не очень хорошая идея.

Исключение должно быть автономным. Он должен владеть всей памятью, необходимой для того, что он должен делать.

Кроме того, вы не правильно унаследовали от std::exception. В частности, вы должны перегрузить метод virtual const char* what() const throw(). Опять же, я удивлен, что это позволило вам скомпилировать свой код без него.

0 голосов
/ 07 декабря 2011

Это будет зависеть от вашего компилятора. С настройками gcc по умолчанию вы можете просто выбросить вещи без броска (...) в прототипе.

Я использую объявления броска в прототипе, когда я хочу уменьшить количество бросаемых «вещей». Поэтому int myfunc () throw (string) будет разрешать только строки (или производный класс строки, которые будут выброшены).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...