Симптомы были очень неясные -- в некотором месте программа зависала, при этом в коде там не было строчек, где можно зависнуть.
Спустя 4 дня отладки я обнаружил наконец, в чём заключалась ошибка в коде. Вот отрывок. Зависание иногда происходило где-то в нём, причём один раз на 10-20 выполнений.
bFlag=GetStatus();
fTime=0;
while(!bFlag&&fTime<0.5);
{
//do something
fTime=TimeElapsed();
bFlag=GetStatus();
}
Вписать в само условие GetStatus() по некоторым причинам было нельзя (я привожу тут текст упрощённо). Функция TimeElapsed() возвращает, сколько прошло времени с начала ожидания. Если прошло 0.5 секунды, дальше мы начинаем сушить вёсла, продолжение нормальной работы невозможно. Функция GetStatus() проверяет состояние другого потока в многопоточном приложении -- не возникло ли в нём определённое событие? Если статус равен фолс (не возникло), ждём дальше. Если тру (возникло) -- выходим. Специфика её работы такова, что вернувши один раз тру, дальше она начинает возвращать фолс -- до следующего возникновения события во втором потоке. Я долго грешил на ошибки синхронизации, тыкал палочкой в критические секции -- безрезультатно. Пока не обнаружил при помощи отладочной печати странную вещь. bFlag до цикла равно тру, а внутри цикла -- фолс. В тех случаях, когда программа не зависала. Это значит, что ГетСтатус вызывался два раза. Это невозможно, т.к. Если он равен тру, в цикл вход происходить был не должен -- условие сразу ложно! И тут я присмотрелся повнимательнее...
***
Когда я ещё не имел опыта программирования на Си, классе так в восьмом-девятом, я всё же написал одну довольно об'ёмную по тем меркам программу. Но она не работала. Это была компьютерная игра. Основной цикл был прост, как число 3. Прорисовать экран -- дать пользователю сделать ход -- если конец игры достигнут, сделать выход. И с начала. Проблема была в следующем месте:
1 while(1);
2 {
3 Draw();
4 GameMove();
5 if(GameOver())
6 break;
7 }
Это плохой стиль. Не рекомендуется делать бесконечный цикл в тех условиях, когда чётко понятно условие выхода. Это допустимо делать, когда этих условий много и они сложно комбинируются.
При отладке наблюдалась странная ситуация -- после строчки 1 программа зависала. Я нажимал "следующую строку", но она продолжала висеть на этой. Кроме всего прочего выдавался варнинг -- unreachable code на строках 3-6. Это было очень странно. Я же всё чётко написал! Строчка должна выполняться. Я искал ошибку полгода, с перерывами. Потом до меня допёрло -- в первой строке в конце стояла точка с запятой. Это и было тело цикла. Т.е. это был бесконечный пустой цикл. И он бесконечно выполнялся, не переходя к строчке 3.
Я каждый год предупреждаю об этом всех студентов. И сам, спустя много лет, попал в ту же ловушку. Но попадание туда было закономерным -- дальше по тексту был похожий цикл, но с постусловием. Очень похожим. Чтобы не писать два раза (по факту оно было несколько сложнее, чем я привожу в примере), я его просто скопировал. А в цикле с постусловием точка с запятой быть как раз должна.
Вообще первый отрывок написан очень плохо. Его надо было тоже делать с постусловием.