Как мне отладить трудно воспроизводимый сбой без полезного стека вызовов?

Я столкнулся со странным сбоем в нашем программном обеспечении, и у меня много проблем с его отладкой, поэтому я ищу совета SO о том, как решить эту проблему. это.

Авария - это нарушение прав доступа при чтении указателя NULL:

Первое случайное исключение в $ 00CF0041. Класс исключения $ C0000005 с сообщением 'нарушение доступа по адресу 0x00cf0041: чтение адреса 0x00000000 '.

Это случается только «иногда» - мне еще не удалось выяснить рифму или причину, когда - и только в основном потоке. Когда это происходит, стек вызовов содержит одну неверную запись:

Call stack with one line, Classes::TList::Get, address 0x00cf0041

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

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

Вот что я пробовал:

  • Попытка воспроизвести его надежно в определенный момент. Я не нашел ничего, что воспроизводило бы это каждый раз, и пару вещей, которые иногда делают или не делают без видимой причины. Это недостаточно «узкие» действия, чтобы сузить его до определенного раздела кода. Это может быть связано с синхронизацией, но в момент, когда IDE ломается, другие потоки обычно ничего не делают. Я не могу исключить проблему с потоками, но думаю, что это маловероятно.
  • Сборка с дополнительными отладочными операторами (дополнительная отладочная информация, дополнительные утверждения и т. Д.) После этого сбой никогда не происходит.
  • Сборка с ] Codeguard включен. После этого сбой никогда не происходит, и Codeguard не показывает ошибок.

Мои вопросы:

1. Как узнать, какой код вызвал сбой? Как мне сделать эквивалент подъема по стеку?

2. Какой общий совет вы можете дать, как отследить причину этого сбоя?

Я использую Embarcadero RAD Studio 2010 (проект в основном содержит код C ++ Builder и небольшое количество Delphi).

Изменить: Я подумал, что должен добавить, что на самом деле вызвало это. Был поток, который вызвал ReadDirectoryChangesW , а затем, используя GetOverlappedResult , ожидал события, чтобы продолжить, и что-то предпринял с изменениями. О событии также сообщалось, чтобы завершить поток после установки флага состояния. Проблема заключалась в том, что при выходе из потока он никогда не вызывал CancelIO . Как результат, Windows все еще отслеживала изменения и, вероятно, все еще записывала в буфер при изменении каталога, даже несмотря на то, что буфер, перекрывающаяся структура и событие больше не существовали (как и контекст потока, в котором они были созданы). Когда CancelIO был вызван, сбоев больше не было.

15
задан David 22 August 2011 в 07:46
поделиться