Обработка исключений в C ++ с информацией о строке исходного кода - PullRequest
2 голосов
/ 05 января 2010

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

Моя среда - Windows с VC ++ на VS2008

Ответы [ 11 ]

3 голосов
/ 05 января 2010

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

3 голосов
/ 05 января 2010

Если вы действительно хотите регистрировать информацию об исключениях C ++ (AV не одно), выброшенных из вашего кода, вы можете использовать макросы __FILE__ и __LINE__ в конструкторах типов исключений.

2 голосов
/ 06 января 2010

Если вы перехватываете исключение SEH с помощью обработчика __catch, вы можете получить доступ к контексту потока во время исключения и затем использовать StackWalk64 для выгрузки стека вызовов в точке, где было сгенерировано исключение. Обратите внимание, что, как я упоминал здесь: Печать трассировки стека в C ++ (MSVC)? StackWalker от Йохена Кальмбаха [MVP VC ++] и доступная в codeproject, вероятно, самый простой способ сделать это. Он включает в себя все детали работы с базовым API StackWalk64.

В качестве альтернативы вы можете использовать то же решение, которое я предложил здесь: Как отловить ошибку деления на ноль в Visual Studio 2008 C ++? для преобразования структурированных исключений Windows в исключения C ++ и записи трассировки стека как показано выше в точке, где вы переводите исключение. Это даст вам исключение C ++ с трассировкой стека, как вы получаете в C # или Java.

1 голос
/ 05 января 2010

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

1 голос
/ 05 января 2010

В MSVC вы можете настроить отладчик так, чтобы он прерывался, когда происходит какое-либо исключение или что-то подобное, например, нарушение доступа. Для этого перейдите в раздел отладка-> Исключения и установите соответствующий флажок.

Обратите внимание, что нарушения доступа не являются исключениями в C ++ и будут обрабатываться по-разному в разных системах. В Windows вы можете перехватить их с помощью структурированного обработчика исключений. В unixy системах это обычно дамп памяти. Обычно от этого можно получить трассировку стека.

1 голос
/ 05 января 2010

Я не уверен, почему тестеры должны знать, в какой строке произошло исключение.

Однако разработчики могут захотеть узнать. Но лучший подход заключается в следующем:

  1. Включите информацию о классе и методе с каждым исключением PROGRAM. Это исключения, которые НЕ должны были случиться.

  2. Это должно быть выведено любым журналом ваших исключений. Ваша программа ловит и регистрирует каждое исключение, не так ли? Если нет, то следует.

  3. Убедитесь, что ваши методы достаточно малы, чтобы вышеприведенного было достаточно для легкого отслеживания ошибки. Если вам также нужна информация о строках, ваши методы слишком велики, а исключения недостаточно конкретны.

0 голосов
/ 15 сентября 2011

В Windows системная функция времени выполнения C _set_se_translator () принимает простую статическую функцию с сигнатурой

void f(int, EXCEPTION_POINTERS*)

ни один из аргументов вам совершенно не нужен. В теле f брось свое любимое исключение. Вызовите функцию в начале вашей программы. Документация разумна для майкрософт.

С помощью этой функции вы можете выполнять множество дополнительных действий.

В проекте Google Breakpad есть много хороших вещей. Среди них есть средства для преобразования адреса сбоя в имя файла, строки и функции с использованием символов сборки и библиотеки debuginfo.

0 голосов
/ 05 января 2010

В одном проекте, над которым я работал, корневой класс используемой иерархии исключений захватил стек вызовов в конструкторе на тот случай, если позже понадобится информация для отладки после того, как исключение будет перехвачено. Это была достойная идея, хотя, если вы ловите и «обрабатываете» исключение, то, когда оно было сгенерировано, не должно иметь большого значения.

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

0 голосов
/ 05 января 2010

Мой ответ относится только к Windows. У вас есть несколько вариантов:

Без изменения вашего кода -

  • Избегайте перехвата исключений (по крайней мере, тех, которые вы не ожидаете), и пусть ваше приложение просто падает. Настроить добрый старый доктор. watson (drwtsn32.exe), чтобы создать аварийный дамп и открыть этот дамп в своем отладчике. Там вы получите точную строку кода.
  • Используйте adPlus (из установки windbg), чтобы отслеживать запуск вашего приложения и создавать дамп при возникновении исключения.

Из своего кода вы можете -

Наконец, здесь было задано довольно много вопросов по этому вопросу. Посмотрите вокруг, и вы получите дополнительные ответы.

0 голосов
/ 05 января 2010

В системах типа unix нарушение доступа генерирует сигнал SEGV или BUS. Это обычно вызывает приложение к дампу ядра. Вы всегда можете написать свой собственный обработчик сигнала. Оттуда вы, вероятно, могли бы создать дамп стека с помощью glibc перед дампом ядра.

Дамп ядра обычно дает вам все это для тщательного анализа в gdb.

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