У меня есть большое приложение, которое недавно начало показывать довольно странное поведение при работе в отладчике.Во-первых, основы:
OS: Windows 7 64-bit.
Application: Multithreaded VCL app with many dlls, bpls, and other components.
Compiler/IDE: Embarcadero RAD Studio 2010.
Наблюдаемый симптом заключается в следующем: хотя отладчик подключен к моему приложению, определенные задачи вызывают сбой приложения.Более того, подробности вызывают недоумение: мое приложение останавливается с сообщением Windows, в котором говорится: «Ваше приложение перестало работать».И это услужливо предлагает отправить мини-дамп в Microsoft.
Следует отметить: приложение не падает, когда отладчик не подключен.Кроме того, отладчик не указывает никаких исключений или других проблем во время работы приложения.
Установка и переход через точки останова, похоже, влияют на точку сбоя приложения, но я подозреваю, что это является признаком отладки.поток, отличный от проблемного.
Эти сбои также происходят на компьютерах моих коллег с тем же поведением, которое я наблюдаю.Это заставляет меня не подозревать, что что-то не удалось установить на мой компьютер.Мои коллеги, столкнувшиеся с этой проблемой, также работают под управлением Windows 7 64-bit.У меня нет коллег, не сталкивавшихся с проблемой.
Я собрал проанализированный ряд полных дампов сбоев.Я обнаружил, что сбой на самом деле происходил в том же месте каждый раз.Вот данные об исключениях из дампов (они всегда одинаковы, за исключением, конечно, ThreadId):
Exception Information
ThreadId: 0x000014C0
Code: 0x4000001F Unknown (4000001F)
Address: 0x773F2507
Flags: 0x00000000
NumberParameters: 0x00000001
0x00000000
Google показывает, что код 0x4000001F на самом деле является STATUS_WX86_BREAKPOINT.Microsoft бесполезно описывает его как «Код состояния исключительной ситуации, который используется подсистемой эмуляции Win32 x86».
Вот подробности стека (которые, кажется, не меняются):
0x773F2507: ntdll.dll+0x000A2507: RtlQueryCriticalSectionOwner + 0x000000E8
0x773F3DAB: ntdll.dll+0x000A3DAB: RtlQueryProcessLockInformation + 0x0000020D
0x773D2ED9: ntdll.dll+0x00082ED9: RtlUlonglongByteSwap + 0x00005C69
0x773F3553: ntdll.dll+0x000A3553: RtlpQueryProcessDebugInformationRemote + 0x00000044
0x74F73677: kernel32.dll+0x00013677: BaseThreadInitThunk + 0x00000012
0x77389F02: ntdll.dll+0x00039F02: RtlInitializeExceptionChain + 0x00000063
0x77389ED5: ntdll.dll+0x00039ED5: RtlInitializeExceptionChain + 0x00000036
Стоит отметить, что в 0x773F24ED, по-видимому, имеется функциональный эпилог, что скорее говорит о том, что RtlQueryCriticalSectionOwner является красной сельдью.Аналогично, эпилог функции ставит под сомнение RtlQueryProcessLockInformation.Смещение 0x5C69 ставит под сомнение RtlUlonglongByteSwap.Однако другие символы выглядят корректными.
В частности, RtlpQueryProcessDebugInformationRemote выглядит корректно.Некоторые люди в Интернете (http://www.cygwin.com/ml/cygwin-talk/2006-q2/msg00050.html), похоже, думают, что он создан отладчиком для сбора отладочной информации. Мне кажется, что эта теория звучит правдоподобно, поскольку она появляется только при подключенном отладчике.
Как всегда, когда что-то сломалось, что-то изменилось, что сломало это. В этом случае, что-то динамически загружает новую DLL. Я могу заставить аварийное прекращение происходить, не динамически загружая конкретную DLL. Я не уверен, чтозагрузка dll связана, но вот подробности, на всякий случай:
Источник dll - C. Вот параметры компиляции, которые не установлены по умолчанию:
Language Compliance: ANSI
Merge duplicate strings: True
Read-only strings: True
PCH usage: Do not use
Dynamic RTL: False
(В параметрах проекта указано, что False является значением по умолчанию для динамического RTL, хотя при создании проекта DLL было установлено значение True.)
DLL загружается с помощью LoadLibrary и освобождается с помощью FreeLibrary. Кажется, все в порядке сзагрузка и выгрузка модуля. Однако вскоре после выгрузки библиотеки (с FreeLibrary) вышеупомянутый потоквылетает программа.Для отладки я удалил все реальные вызовы библиотеки (в том числе, для дальнейшего тестирования, DllMain).Никакая комбинация вызовов или не вызовов, DllMain или DllMain, или чего-либо еще, казалось, никак не изменила поведение аварии.Простая загрузка и выгрузка dll вызывает сбой позже.
Кроме того, изменение библиотеки DLL для использования динамического RTL также приводит к прекращению сбоя потока отладчика.Это нежелательно, потому что скомпилированная dll действительно должна использоваться без доступной среды выполнения CodeGear.Также важен размер dll.Код C, содержащийся в dll, не использует никаких библиотек.(Он не содержит заголовков, даже заголовки стандартных библиотек. Нет malloc / free, нет printf, нет ничего. Он содержит только функции, которые зависят исключительно от их входных данных и не требуют динамического выделения.) Это также нежелательно, поскольку «исправление»ошибка, изменяя вещи, пока они не работают, не понимая, почему это работает, на самом деле никогда не является хорошим планом.(Это имеет тенденцию приводить к повторению ошибок и странным методам кодирования. Но на самом деле, на этом этапе, если я не могу найти что-то еще, я могу признать поражение по этому счету.)
И, наконец, моя проблема можетбыть связано с одной из этих проблем:
Буду признателен за любые идеи или предложения.