Я использую потоки в течение 20 лет в Unix и просто изучаю их в Windows с Visual Studio 2008.
Мое приложение представляет собой основанный на диалогах MFC GUI с четырьмя основными «равноправными» окнами (ни одно из них не является «главным» окном). Когда MyApp :: InitInstance () запускается, окно Debug-> Windows-> Threads сообщает только об одном потоке MainThread. Когда я прохожу мимо первый CDialog::Create()
вызов, 3 рабочих потока созданы. Я не знаю, что это такое, и я бы с удовольствием — и особенно хотел бы иметь ссылку на книгу с полным объяснением или веб-страницу. Я пытался поставить точку останова на CreateThread()
но VS2008 сообщает: The function cannot be found.
в наведении !
значок в окне точек останова. Я также не могу сделать один шаг, если нарушу функцию, которая ее вызывает. Я предполагаю, что это системный вызов, и как код ядра VS08 не может проникнуть в него.
Затем я создаю рабочий поток, который выводит аудио и для которого установлено значение THREAD_PRIORITY_TIME_CRITICAL. Это работало стабильно в течение длительного времени.
Однако, как только мое приложение покидает MyApp :: InitInstance (), возникает таинственная нить созданный с «Приоритетом», показанным как -8 в окне Отладочных потоков. Я не знаю, что это за нить. Любые идеи или указатели на ресурсы? Я пытался поставить точку останова на SetThreadPriority()
, предполагая, что я ударил бы это в любом коде, устанавливая его на этот не ванильный приоритет, и так же, как CreateThread()
, это не известная функция.
И что касается самой проблемы, в отличие от простой загадки: закрывая свое приложение, я уничтожаю и освобождаю всю память, которую я использовал, и получаю сбой в этом потоке «-8», пока я делаю это. Там нет источника, только сборка, и нет трассировки стека или символов. Нет никаких намеков на то, что программа повреждает кучу, например, символы появляются в ее стеке или в окне вывода.
Единственная дополнительная информация, которую я могу дать о приложении, это то, что:
— он принимает события MIDI хорошо и имеет в течение многих лет
— имеет один рабочий поток, вычисляющий данные для звукового буфера; Я установил дозорный булевский флаг и жду, пока он закончится GetExitCodeThread()
; Я действительно получил код выхода, так что я уверен, что это не поток -8. (И в любом случае его приоритет — TimeCritical, а не -8)
— все без проблем, за исключением утечек памяти, которые я сейчас решаю, используя _CRTDBG_MAP_ALLOC
, Без освобождения данных у меня не происходит сбоя. Но выяснив, какой именно объект вызывает проблему, я все еще в растерянности, потому что — опять же — я фактически не создал поток, который ссылается на этот объект.
Многие библиотеки, включая MFC, создают дополнительные рабочие потоки или пулы потоков как часть их нормальной работы. Это не о чем беспокоиться.
Если вы действительно хотите точно знать, где создаются эти потоки, проблема с настройкой точки останова на CreateThread
в том, что отладчик не может разрешить имя символа. Вы должны помочь ему, сообщив, в каком модуле он находится, используя специальный синтаксис {,,module}symbol
(подробнее об этом Вот). Кроме того, имя может быть украшено, поэтому действительное имя символа, которое работает, может быть любым из {,,kernel32.dll}CreateThread
, {,,kernel32.dll}_CreateThread}
, или же {,,kernel32.dll}_CreateThread@44
, Аналогично для SetThreadPriority()
,
Я также настоятельно рекомендую настроить отладчик на использовать серверы символов Microsoft, если вы еще этого не сделали Это даст вам гораздо более полезную символизацию адресов функций в DLL-библиотеках Microsoft (включая MFC), чтобы дать вам лучшее представление о том, что он делает.
Тем не менее, зная, где создается этот поток, скорее всего, не поможет вам. Скорее всего, у вас происходит какое-то повреждение кучи из-за переполнения буфера где-то. Когда вы освобождаете буфер, который был переполнен, повреждение будет ухудшаться, потому что менеджер кучи будет следовать за поврежденными указателями и начать запись в другие случайные места памяти; в то время как не освобождение поврежденных буферов с меньшей вероятностью приведет к сбою процесса. Отслеживание того, где именно происходит кучная коррупция, будет сложной задачей.
Благодаря вашей помощи в выяснении, как создать точку прерывания создания потока. Сразу стало ясно, что он создается внутри библиотеки обработки аудио. Когда кто-то дает этой библиотеке блок памяти, содержащий сэмплы для воспроизведения, и у меня была свободная игра, это был главный кандидат.
Читая между строк в документации Microsoft, я обнаружил две дополнительные функции, которые могут потенциально закрыть такой поток waveOutReset()
а также waveOutClose()
, После их вызова нарушения доступа исчезли. С этим типом ошибки трудно быть уверенным, но для меня это кажется вероятной причиной проблемы.
В течение многих лет программа просто выполнялась по команде пользователя, не освобождая память и не имела проблем. Только после добавления кода очистки проблема стала видимой. Эти факты также подтверждают предполагаемую причину.