перебросить исключение, сохраняя обратную трассировку - PullRequest
0 голосов
/ 18 сентября 2018

Мне нужно поймать какой-нибудь "фатальный" C ++ exception, затем очистить журналы и перебросить прежнее, с его собственной обратной трассировкой .

Однако мое текущее решение отображает (правильно) неправильная трассировка стека.

#include <exception>
#include <iostream>

void fatal(const std::exception & E)
{
    // do - something - extremely - important
    throw E;
}

int foo()
{
    throw std::runtime_error("yet another foo function");
}

int main()
{
    try
    {
        return foo();
    }
    catch (const std::exception & E)
    {
        fatal(E);
    }
    return -1;
}

Программа упакована в

  $ cat ./backtrace
  backtrace
  quit

  $ ulimit -c unlimited
  $ ./a.out
  $ gdb -q ./a.out core -x ./backtrace

Результат

Программа завершена с сигналом SIGABRT, прервано.

..................................................

4 0x00007f496eb53701 в std :: terminate () () из /usr/lib/x86_64-linux-gnu/libstdc++.so.6

5 0x00007f496eb53919 в __cxa_throw () из /usr / lib / x86_64-linux-gnu / libstdc ++. so.6

6 0x0000000000400d71 со смертельным исходом (std :: exception const &) ()

7 0x0000000000400e5b в основном ()

Я думал, что отбрасывание исключения (по const ref) - это техника для передачи первоначального обратного следа;Я заинтересован в возврате foo(), а не fatal().

Ответы [ 2 ]

0 голосов
/ 18 сентября 2018

С вашим скриптом:

backtrace
quit

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

Другой подход заключается в использовании команды gdb catch throw, плюс немного сценариев. Таким образом, вы можете захватить трассировку стека в каждом throw. Вы могли бы сделать это так:

(gdb) catch throw
Catchpoint 1 (throw)
(gdb) commands
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
> silent
> backtrace
> continue
> end

Это будет останавливаться на каждом throw и печатать обратную трассировку. Однако вы не хотите выводить следы стека из фрейма fatal. Для этого вы можете использовать вспомогательную функцию GDB и сделать условную точку захвата условной:

(gdb) cond 1 $_any_caller_matches("fatal", 10)

(«10» - это всего лишь предположение о том, сколько кадров может отделить fatal от внутренней части библиотеки C ++, которая обрабатывает бросок.)

0 голосов
/ 18 сентября 2018

Я не уверен, что вы пытаетесь выполнить здесь, но чтобы перебросить исключение, вам нужно написать throw; (без аргументов), throw E; сгенерирует новый экземпляр исключения, скопировав его из существующего объекта.

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

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