Необработанное исключение в потоке отладчика Rad Studio

У меня есть большое приложение, которое недавно начало показывать довольно странное поведение при работе в отладчике. Во-первых, основы:

OS: Windows 7 64-bit.
Application: Multithreaded VCL app with many dlls, bpls, and other components.
Compiler/IDE: Embarcadero RAD Studio 2010.

Наблюдаемый симптом заключается в следующем: пока отладчик подключен к моему приложению, определенные задачи вызывают сбой приложения. Подробности еще больше сбивают с толку: мое приложение останавливается с сообщением Windows: «Ваше приложение перестало работать». И он услужливо предлагает отправить минидамп в Microsoft.

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

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

Эти сбои также происходят на компьютерах моих коллег, с тем же поведением, которое я наблюдаю. Это заставляет меня не подозревать, что что-то не удалось установить на моем компьютере. Мои коллеги, столкнувшиеся с этой проблемой, также используют 64-разрядную версию Windows 7. У меня нет коллег, не столкнувшихся с этой проблемой.

Я собрал и проанализировал несколько полных дампов сбоев. Я обнаружил, что сбой каждый раз происходил в одном и том же месте. Вот данные исключения из дампов (они всегда одни и те же, за исключением, конечно, 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

(The Project Параметры говорят, что по умолчанию для динамического RTL установлено значение False, хотя при создании проекта dll для него было установлено значение True.)

DLL загружается с помощью LoadLibrary и освобождается с помощью FreeLibrary. С загрузкой и выгрузкой модуля вроде все нормально. Однако вскоре после выгрузки библиотеки (с FreeLibrary) вышеупомянутый поток вызывает сбой программы. Для отладки я удалил все фактические вызовы библиотеки (включая, для большего тестирования, DllMain). Никакая комбинация вызовов или невызовов, DllMain или отсутствие DllMain, или что-то еще, казалось, никак не изменило поведение сбоя. Простая загрузка и выгрузка dll вызывает сбой позже.

Кроме того, изменение dll для использования динамического RTL также приводит к прекращению сбоя потока отладчика. Это нежелательно, потому что скомпилированную dll действительно можно использовать без доступной среды выполнения CodeGear. Также важен размер dll. Код C, содержащийся в dll, не использует никаких библиотек. (Он не включает заголовки, даже заголовки стандартной библиотеки. Нет malloc / free, нет printf, нет ничего. Он содержит только функции, которые зависят исключительно от их входных данных и не требуют динамического выделения.) Это также нежелательно, потому что "исправление" a ошибка, изменяя что-то до тех пор, пока оно не сработает, не понимая, почему это работает, на самом деле никогда не был хорошим планом. (Это имеет тенденцию приводить к повторению ошибок и странным методам кодирования. Но на самом деле, на данном этапе, если я не могу найти ничего другого, я могу признать поражение по этому поводу.)

И, наконец, моя проблема может быть связана с одна из следующих проблем:

Мы будем благодарны за любые идеи или предложения.

14
задан Community 23 May 2017 в 11:54
поделиться