Нахождение деления на нуль в большом проекте

Недавно, наш большой проект начал отказывать на необработанном делении на нуль. Никакой недавний код, кажется, не содержит вероятных элементов, таким образом, это могут быть новые наборы данных, влияющие на старый код. Проблемой является кодовая база, является довольно большим, и работа встроенного устройства без удобного доступа отладки (отладка сделана большим количеством printf () s по последовательной консоли, нет никакого gdb для устройства и даже если бы было, то двоичный файл, скомпилированный с отладочными символами, не соответствовал бы).

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

Вопрос состоит тогда также в том, как найти все операции деления в большом (~200 файлов, некоторые большой) проектом C++, или, если у Вас есть лучшая идея, как определить местоположение ошибки, дайте им.

дополнительная информация: проект работает на встроенном ARM9, маленьком пользовательском дистрибутиве Linux, кросс-скомпилированном с Cygwin/Windows crosstools, IDE является Eclipse, но существует также Cygwin со всеми соответствующими положительными героями. Вещью является проект, является очень определенным для аппаратных средств, и катастрофические отказы происходят только при выполнении на полную мощность, все существенные взаимосвязанные активные модули. Ограниченный "режим отказа", где только скелет активны, не создает их.

9
задан John Carter 1 February 2010 в 15:51
поделиться

10 ответов

Найти все подразделения не составит труда с помощью специального поиска grep . Вы можете легко отличить такое использование от других случаев использования символа / и % в C ++.

Кроме того, если вы знаете, что разделяете, вы можете глобально перегрузить оператор / и % , чтобы получить __ FILE __ и __ LINE __ информирующее утверждение. При использовании файла makefile несложно включить код настраиваемого оператора во все связанные файлы, не касаясь кода.

6
ответ дан 4 December 2019 в 06:49
поделиться

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

6
ответ дан 4 December 2019 в 06:49
поделиться

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

Взгляните на этот вопрос или просто поищите в Google информацию, относящуюся к перехвату исключений в вашей конкретной среде.

Кстати, я думаю, что деление может произойти в результате вызова внешней библиотеки , поэтому не на 100% уверен, что вы найдете виновника только путем смазывания вашего кода.

8
ответ дан 4 December 2019 в 06:49
поделиться

Если я правильно помню, ARM9 не имеет аппаратного разделения, поэтому он будет реализован в вызов функции, который компилятор делает всякий раз, когда ему нужно выполнить деление.

Посмотрите, реализует ли ваш набор инструментов разделение на ноль так же, как набор инструментов ARM (вероятно, он делает что-то похожее). Если это так, вы можете установить обработчик, который вызывается при возникновении проблемы, и вы можете printf () регистрировать и стек, чтобы вы могли определить, где возникает проблема. Возможная аналогичная альтернатива - ваш небольшой дистрибутив Linux подает сигнал, который вы можете уловить.

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

8
ответ дан 4 December 2019 в 06:49
поделиться

Обращайтесь с исключением.

Обычно исключение будет вручено структуру, содержащую адрес, который вызвал исключение и другую информацию. Возможно, вам придется познакомиться с таблицей данных микроконтроллера или Руководство по RTOS.

2
ответ дан 4 December 2019 в 06:49
поделиться

PC-Lint может помочь, это похоже на FindBugs для C ++. Это коммерческий продукт, но есть гарантия возврата 30 денег.

2
ответ дан 4 December 2019 в 06:49
поделиться

Единственный способ найти эти условия - обычный:

  1. попытаться воспроизвести проблему, не глядя на исходный текст (так как ошибка уже произошла, у вас должна быть информация о той части программы, на которую она влияет)
  2. если она найдена, проверить исходный текст на этот счет и исправить его, иначе:
    . 2.1. grep для каждого / не сопровождается * или / (grep "/[^/*]" я думаю)
    . 2.2. найти условия, для которых выполняется код и воспроизвести его
0
ответ дан 4 December 2019 в 06:49
поделиться

Используйте TEMPS для GCC и найдите соответствующую сборку для разделения в сгенерированном файле .s. Если вам повезло, это будет что-то довольно отличительное, возможно, даже функция вызова. Если это функция, вы можете использовать слабую ссылку, чтобы переопределить его собственной проверенной версией. В противном случае распознавание подразделений в Собрании должна дать вам очень хорошую идею, где они находятся в коде C / C ++, и вы можете непосредственно их инструментировать.

1
ответ дан 4 December 2019 в 06:49
поделиться

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

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

0
ответ дан 4 December 2019 в 06:49
поделиться

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

см. http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4061.html

Я бы предложил предусмотреть __rt_raise(), как сказано на странице выше.

__rt_raise(2,2) будет вызываться, когда процедура деления обнаружит деление на ноль. Таким образом, вы можете вывести регистр LR. и затем использовать addr2line для перекрестной ссылки на исходную строку

1
ответ дан 4 December 2019 в 06:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: