2011-01-04 5 views
3

У меня есть приложение, которое выполняет измерения каждую секунду (я запускаю его в демо-режиме &, генерируя случайные данные, поэтому проблема не связана с чтением с устройств, подключенных к последовательному порту).Как отлаживать мою программу, когда она зависает?

Через 5-6 минут он висит.

Я добавил

try 
    // entire body of procedure/function goes here 

except 
    on E: Exception do 
     begin 
      MessageDlg('Internal coding error in <function name>()', 
          mtError, [mbOK], 0); 
     end; 
end; 

для каждой функции (и Application.Run() в файле проекта), но я не вижу никаких сообщений диалогов. Любая идея, как я могу это проверить?


Обновление: Я woudl думаю, сидеть, чтобы быть проблемой ресурсов, либо ОЗУ или MySql базы данных - но другие программы работают нормально, и это только 5 поплавки и метку времени, которые получают сохраненные с каждым измерением, так как кажется маловероятным после такого короткого времени.


Решение было много отличных ответов (спасибо и +1 круглые), но я, наконец, получил его (как это было предложено), запустив в IDE и с помощью Run/Pause, чтобы увидеть, что это все большее петля.

Еще раз спасибо.

+2

* отладить это? ... – berkay

+0

oops. Благодарю. +1 – Mawg

ответ

5

Я хотел бы попробовать следующее:

  1. Attach и нажмите Pause и посмотреть, где он находится, какие потоки запущены, что ждет нити (если все из них, то у вас есть тупик).

  2. Рефакторинг вашего основного метода в кучу маленьких (возможно, вы уже это сделали), а затем замените маленькие на фиктивные/жестко закодированные значения. Это может помочь, но не обязательно определить неисправный блок.

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

  4. Если вы используете сокеты, убедитесь, что тайм-аут чтения установлен на бесконечность. Если да, то измените значение на некоторое время и следите за таймаутами.

  5. В .NET можно включить обработку всех исключений, что означает, что перед обработкой кода (например, в инструкции catch) среда IDE разрывается в точке исключения. Включите это, если возможно, в Delphi и посмотрите, получаете ли вы его.

+0

Спасибо, хороший совет (+1). (см. небольшое обновление до вопроса) – Mawg

+1

Добавлен бюллетень №4. – Schultz9999

+0

Добавлен бюллетень №5. – Schultz9999

1

Если вы не видите исключение перед добавлением обработчиков исключений, вы не будете создавать MessageDlgs для просмотра.

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

+0

«Если вы не видите исключения перед добавлением обработчиков исключений, вы не будете создавать MessageDlgs, чтобы увидеть« ... d'oh !! (+1) Да, возможно, цикл ... Я обновляю stringgrid и рисую каждое измерение (1 секунду), но поскольку данные добавляются в конце, это не должно быть проблемой (я думаю), однако я буду исследовать это , (trace?) – Mawg

+0

Сначала я должен был бы узнать, где проблема, а затем установить точку останова в начале этого раздела.Если вам нужно отслеживать 5 минут нормальной работы программы, это может занять несколько дней! –

5

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

Запустите программу под отладчиком. Пусть он бежит, пока он не повесится. Когда он зависает, переключитесь на отладчик и выберите «Debug: Break All» (или эквивалент), чтобы отладчик заморозил все потоки и взял управление процессом.

Теперь откройте режим Threads в отладчике и проверьте трассировки стека каждого потока в вашей программе. Начните с основного потока, очевидно. Обязательно просмотрите стек вызовов для нескольких вызовов, чтобы узнать, распознаете ли вы какой-либо из вашего кода. Если вы найдете трассировку стека, которая находится в середине цикла, изучите локальные переменные, чтобы увидеть, как ваша контрольная переменная цикла каким-то образом проскользнула мимо условия выхода и поставила вас в бесконечный цикл.

Если трассировка стека указывает на то, что каждый поток заблокирован в ожидании какого-либо внешнего события, у вас может быть тупиковая нить - поток A принимает блокировку A, а затем пытается закрепить блокировку B, в то время как нить B удерживает блокировку B и пытается возьмите блокировку A. Если вы не используете нити в своей программе, это менее вероятно, но все равно следить за ней.

Если ничто нечетное выскакивает на вас после просмотра трассировки стека потоков, пусть программа запустится на несколько секунд, затем снова вломится в нее с помощью отладчика и посмотрит вокруг. Посмотрите, что отличается от трассировки стека.

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

+0

+1 Спасибо, сделаю. Я сомневаюсь, что это проблема нитей. Вероятно, убегающий цикл, но спасибо за отзывы. – Mawg

1

Во-первых: попробуйте отладить его в среде Delphi. Во-вторых: если вы не можете этого сделать (на клиентском ПК), попробуйте «Проектор просмотра стека» моего профилировщика (с открытым исходным кодом): http://code.google.com/p/asmprofiler/wiki/ProcessStackViewer
(вам нужна информация об отладке: файл .map или .jdbg) Затем посмотрите на стек ваших потоков (вероятно, основной/первый поток). Затем вы можете опубликовать трассировку стека (если вы не можете найти проблему).

0

Если вам нужна помощь с такого рода вещами в приложении, для которого вы не можете использовать IDE, то что-то вроде madExcept может многое помочь. У этого есть автоматическая проверка замораживания для основного потока, и вы можете иметь это, давая дамп стека, чтобы показать, что он делал, когда он был заморожен. Пользователь может выбрать, чтобы убить или продолжить, и приложение может сказать madExcept, потому что оно занято, а не в случае необходимости предупреждать (для длительного анализа или печати или чего-то еще).

Смежные вопросы