Как правильно отладить и найти причины сбоев? - PullRequest
6 голосов
/ 03 июня 2010

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

Я не могу вспомнить, какие изменения я внес в программу, которая могла вызвать сбои, это было так долго. Но, к счастью, предыдущая версия не дает сбоя, поэтому я могу просто скопировать немного кода и потратить 10 часов, чтобы увидеть, в какой момент он начинает падать ... Я не думаю, что хочу сделать это пока.

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

Я создал «безопасную» функцию free (), она проверяет указатель, если он не равен NULL, а затем освобождает память, а затем устанавливает указатель на NULL. Разве это не так, как это должно быть сделано?

Я наблюдал за использованием памяти диспетчера задач, и непосредственно перед тем, как он рухнул, он начал кушать в 2 раза больше памяти, чем обычно. Также загрузка программы становилась экспоненциально медленнее каждый раз, когда я загружал файлы; Первые несколько нагрузок не казались намного медленнее друг от друга, но затем началось быстрое удвоение скорости загрузки. Что это должно сказать мне о катастрофе?

Кроме того, нужно ли вручную освобождать векторы c ++ с помощью clear ()? Или они освобождаются после использования автоматически, например, если я выделю вектор внутри функции, будет ли он освобождаться при каждом завершении функции? Я не храню указатели в векторе.

-

Коротко: я хочу научиться ловить этих чёртовых багов как можно быстрее, как мне это сделать? Использование Visual Studio 2008.

Ответы [ 7 ]

3 голосов
/ 03 июня 2010

«Случайный» сбой, который происходит через некоторое время после сложной операции, почти наверняка является результатом повреждения кучи. Ошибки повреждения кучи - сука , так как они обычно проявляются очень далеко от места, которое фактически вызвало ошибку. Поскольку я работаю в Windows, я предлагаю использовать Application Verifier , который можно бесплатно загрузить с MS.

Запустите AV, настройте его для просмотра вашей программы и включите все параметры, связанные с памятью. Затем запустите вашу программу под отладчиком. (Эти две вещи заставят вашу программу работать крайне медленно.) Надеемся, что дополнительные проверки, которые выполняет AV, приведут к сбою вашей программы в другом месте, чем вы видели до сих пор, но это будет это реальная причина ошибки.

1 голос
/ 03 июня 2010

"Я не могу вспомнить, какие изменения я внес в программу, которая могла вызвать сбои, это было так долго. Но, к счастью, предыдущая версия не вылетает, поэтому я мог просто скопировать немного кода и потратить 10 часов, чтобы посмотретьв этот момент он начинает падать .. "

Вот почему Test-Driven Development (TDD) рушится.Читайте об этом и узнайте, как это может помочь вам избежать этих сценариев.

1 голос
/ 03 июня 2010

Первый вопрос, почему вы используете free () в C ++? Обычно вы должны использовать новый / удалить для управления памятью, или лучше новый в сочетании с умными указателями.

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

Случайные сбои - это обычно / часто ошибки памяти, я бы порекомендовал вам установить хороший отладчик памяти. В Windows это обычно означает Rational Purify или Boundschecker. Конечно, это помогает выяснить, что спровоцировало сбой, в первую очередь - не справиться с нехваткой памяти? Нулевой указатель разыменования? Космические лучи?

Учитывая ответ на комментарии в вашем вопросе, вот что я бы сделал:

  • Измените перехват исключений VS2008 таким образом, чтобы он нарушался при нарушении прав доступа
  • Запустите вашу программу под отладчиком, в режиме отладки - не пытайтесь отлаживать исполняемый файл релиза
  • Попробуйте воспроизвести поведение, которое вы видите. Это займет больше времени, чем в режиме релиза, но вы должны в конечном итоге туда добраться Вы, вероятно, также получите несколько ложных срабатываний.
  • Если вы знаете, какой (нулевой) указатель разыменовывается, задайте () указатель и снова запустите программу в отладчике.
1 голос
/ 03 июня 2010

Как уже говорилось ранее, это, скорее всего, утечка памяти где-то.

Visual Studio имеет встроенные инструменты для этого

В основном вы берете два снимка памяти и сравниваете их когда-то

1 голос
/ 03 июня 2010

Скорее всего, вы получаете повреждение памяти. Вы захотите отладчик памяти, чтобы отследить это; Вы можете найти рекомендации здесь .

Я создал «безопасную» функцию free (), она проверяет указатель, если он не равен NULL, а затем освобождает память, а затем устанавливает указатель на NULL.

Проверка на NULL не обязательна, потому что стандартная соответствующая free (то есть VS2008) сделает эту проверку за вас. По-прежнему возможно освободить указатель мусора, который может вызвать проблемы.

Что касается установки указателя на NULL, это может помочь, но это не панацея. Во-первых, вы не можете установить правильный указатель на NULL. Например, если вы сделаете это:

void myfree(void *ptr)
{
    free(ptr);
    ptr = NULL;
}

все, что вы сделали, это установили локальный параметр myfree в NULL. Копия указателя звонящего по-прежнему остается нетронутой.

0 голосов
/ 03 июня 2010

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

0 голосов
/ 03 июня 2010

Обратите внимание на точку зрения Ноа Робертса и Дж.С. Бэнгса - если вы не знакомы с отладчиком, похоже, настало время познакомиться с вами.

Я бы также предложил инструмент, похожий на valgrind - см. ТАК вопрос .

Кроме того, нужно ли вручную освобождать векторы c ++ с помощью clear ()?

Количество

...