C ++: Пользовательское форматирование для исключений, необнаруженных main () - PullRequest
0 голосов
/ 07 октября 2018

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

Как правило, моя библиотека может быть вызванаиз main функции (), написанной конечным пользователем .Конечный пользователь не помещает блок try..catch в main(), потому что конечный пользователь не ожидает этих исключений (их на самом деле следует избегать и / или отлавливать другими ошибочными библиотеками, между моей библиотекой и main(), но онинет, и это то, что нам нужно для отладки).

// The following example would actually be multiple files,
// but to keep this example simple, put it in "<filename>"
// and compile the following with "g++ <filename>".


// library file

class My_Exception
{
public:
  char const* msg;
  My_Exception(char const* msg) : msg(msg) {}
};

void Library_Function(bool rarely_true = false)
{
  if (rarely_true)
    throw My_Exception("some exceptional thing");
}
// note to discerning user: if you use the "rarely_true" feature,
// be sure to remember to catch "My_Exception"!!!!


// intermediate, buggy, library (written by someone else)

void Meta_Function()
{
  Library_Function(true); // hahahaha not my problem!
}


// main program (written by yet someone else, no "try..except"
// allowed here)

int main()
{
  Meta_Function();
}

Когда я запускаю вышеупомянутую программу, я получаю:

terminate called after throwing an instance of 'My_Exception'
Abort (core dumped)

Мне нравится, как появляется сообщение об ошибкерассказывая мне о неисследованном исключении.Я хотел бы знать, как лучше всего добавить хук к My_Exception, чтобы в этой ситуации также выводилась строка msg.

Я хочу зарегистрировать обратные вызовы в системе времени выполнения или добавитьметоды для My_Exception, но я не хочу связываться с самим main().(Я знаю, что эту проблему можно решить, сказав компоновщику использовать другую точку входа, имеющую try..catch и заключив в нее main(), но конечному пользователю будет сложно заставить что-то подобное принять).

Очевидно, что после main() уже есть некоторый код проверки исключений, так как вышеприведенное сообщение было напечатано.Трассировка стека:

#0  0x0000155554c0d428 in __GI_raise (sig=sig@entry=6)
    at ../sysdeps/unix/sysv/linux/raise.c:54
#1  0x0000155554c0f02a in __GI_abort () at abort.c:89
#2  0x000015555502e8f7 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x0000155555034a46 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x0000155555034a81 in std::terminate() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x0000155555034cb4 in __cxa_throw ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00000000004006eb in Library_Function() ()
#7  0x00000000004006f4 in main ()
(gdb)

За исключением: я вообще не понимаю, почему gdb говорит, что программа прерывается в Library_Function.Это звучит неправильно;он должен был по крайней мере выйти из main() после того, как main() не удалось перехватить исключение.Должна быть какая-то языковая деталь, вроде бы она сохраняет стек до тех пор, пока исключение не будет обработано?В любом случае, я отвлекся.

Может быть, мы можем расширить std::terminate() или cxa__throw() или какой-либо другой компонент времени выполнения для печати msg в этом случае?

Как этот вопросотличается

Почему я не могу распечатать ошибку из моего исключения броска?2 ответа - похоже, но 1. мой вопрос связан с объектом исключения (не строкой), и поэтому вопрос о пользовательском форматировании (в заголовке вопроса) является актуальным.2. отсутствует ключевое слово «uncaught» в заголовке, поэтому его трудно найти

Пользовательское сообщение об ошибке повторно выданного исключения, не напечатанное тем, что () 1 ответ - 1. уже содержитответь на мой вопрос в своем вопросе, поэтому не может быть того же вопроса.Если вы не считаете, «какой инструмент колотит гвоздем», то же самое, что и «почему мой молот не работает».2. отсутствует ключевое слово «uncaught» из заголовка

указатель более свободного броска для 'virtual const char ro_err :: StdErr :: what () const' 1 ответ * - 1. уже содержитответ на мой вопрос в их вопросе, поэтому не может быть того же вопроса.Если вы не считаете, «какой инструмент колотит гвоздем», то же самое, что и «почему мой молот не работает».2. пропущено ключевое слово "uncaught" из заголовка

1 Ответ

0 голосов
/ 07 октября 2018

Как предполагает πάντα ῥεῖ, вы можете попробовать это

class myexception : public exception
{
public:    
    const char* what() const noexcept override
    {
        char* ch = "some exceptional thing";
        return ch;
    }
};    

void Library_Function(bool rarely_true = false)
{
    if (rarely_true)
        throw myexception();
}

int main()
{
    try 
    {
        Library_Function(true);
    }
    catch (myexception& err)
    {
        std::cout << err.what();
    }
    return 0;
}
...