Как отслеживать SIGFPE / арифметическое исключение

У меня есть приложение C ++, скомпилированное для Linux, работающих на процессоре ARM Cortexa9, который сбивается с исключением SIGFPPE / арифметиком. Первоначально я думал, что это из-за некоторых оптимизаций, введенных Флаг -O3 -O3 Flag GCC, но затем я построил его в режиме отладки, и он все еще сбивает.

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

    3 raise()  0x402720ac   
    2 __aeabi_uldivmod()  0x400bb0b8    
    1 __divsi3()  0x400b9880

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

Есть ли какие-либо методы для отслеживания причин таких исключений, когда отладчик не может сделать много, чтобы помочь?

Обновление: После хрустания на шестигранные номера, сброс памяти и выполнения криминала стека (спасибо Crashworks) Через этот драгоценный камень в документации компилятора ARM (даже если я не использую компилятор ARM Ltd.):

integer Devision-by-Zero-Zero Ошибки могут быть в ловушке и идентифицированы Повторное реализация соответствующих функций помощника библиотеки C. То поведение по умолчанию, когда происходит разделение на ноль, заключается в том, что при сигнале функция используется или __rt_raise () или __aeabi_idiv0 () повторно реализуются, __aeaabi_idiv0 () называется. В противном случае функция разделения возвращает ноль. __aeabi_idiv0 () поднимает sigfpe с дополнительным аргументом, divbyzero.

Итак, я положил точку останова на __aeabi_idiv0 (_aeabi_lldiv0) et voila!, У меня была полная трасса стека, прежде чем быть полностью разбитым. Спасибо всем за их очень информативные ответы!

Отказ от ответственности: «Победающий» ответ был выбран исключительно и субъективно с учетом веса его предложений в моих усилиях отладки, потому что более одного было информативным и действительно полезным .

9
задан celavek 20 July 2011 в 15:50
поделиться