Форум: "Потрепаться";
Текущий архив: 2003.10.13;
Скачать: [xml.tar.bz2];
ВнизЛюбопытная (и неприятная) проблема с DLL и run-time packages Найти похожие ветки
← →
Digitman (2003-09-23 16:15) [0]Среда - W2kPro(eng) + SP3, D5 (Update 1 , build 6.18)
Исходные данные :
1. Текст DLL-проекта
library MyDll;
uses Windows, Messages, SysUtils;
begin
ExitCode := 1;
end;
сборка с RTP (задействован только VCL50.BPL)
2. Фрагмент текста хост-приложения
procedure TMyForm.Button1Click(...);
var
hModule : THandle;
begin
hModule := LoadLibrary("MyDll.dll"); // [1]
end;
Проблема :
При выполнении строчки [1] (осн.код.поток хост-процесса) происходит неперехватываемое AV-исключение, чего здесь быть не должно ни коим образом.
В то же время, если сборку DLL выполнить без RTP, то все работает как положено, ожидаемым образом : система по LoadLibrary() возвращает 0 с кодом ошибки, фиксирующим отказ при инициализации DLL (эмулируемый нами таким вот простейшим образом)
Вопрос :
Кто-либо в какой-либо среде наблюдает ли сходное явление ? Прошу поделиться соображениями по сему поводу.
← →
Ketmar (2003-09-23 16:45) [1]ShareMem вставить не помогло?
← →
Владислав (2003-09-23 16:47) [2]> Digitman © (23.09.03 16:15)
Бред какой то... Казалось бы, нет для этого причины... Это полный код?
← →
Digitman (2003-09-23 16:48) [3]а с какого боку здесь ShareMem ? даже и пробовать не буду ... никаким боком не касается ... проблема останется, 100%-но уверен
← →
Digitman (2003-09-23 16:51) [4]
> Владислав
можно сказать - да, полный ... ибо проверено уже :
library MyDll;
uses Windows, Messages, SysUtils;
... [1]
begin
ExitCode := 1;
end;
есть ли [1], нет ли - картина не меняется никак
← →
Ketmar (2003-09-23 16:53) [5]а я знаю, с какого боку? просто больше вообще ничего в голову не приходит %-)
← →
Digitman (2003-09-23 16:53) [6]
> Владислав
вижу что "бред") ... но желания и времени трассировать отказывающий код пока нет .. поэтому и спрашиваю - вероятно, есть уже у кого-то готовые соображения на этот счет
← →
Digitman (2003-09-23 16:55) [7]
> Ketmar
ну знаешь ли) .. это смахивает на "а Вы их дустом непробовали ?")
неспортивно, сударь, неспортивно)))
← →
Игорь Шевченко (2003-09-23 16:58) [8]Дополнение:
На NT 4 с той же версией Delphi ситуация аналогичная.
При загрузке DLL выдается честное сообщение: "Ошибка иницализации DLL, производится аварийное завершение процесса", а следом за ним идет AV по адресу в VCL50.BPL
← →
Ketmar (2003-09-23 16:59) [9]>Digitman © (23.09.03 16:55) [7]
а я сегодня тормоз больше, чем обычно %-)
← →
Ketmar (2003-09-23 17:00) [10]а если SysUtils выкинуть?
← →
Digitman (2003-09-23 17:00) [11]оч похоже на то, что при RTP выгружаются раньше чем происходит обращение к DllEntryPoint(DLL_PROCESS_DETACH)
← →
Игорь Шевченко (2003-09-23 17:00) [12]Более детальная диагностика показывает, что испорчен стек :))
← →
Digitman (2003-09-23 17:04) [13]
> Ketmar
нет, SysUtils тоже ни при чем
← →
Игорь Шевченко (2003-09-23 17:05) [14]Первое исключение встречается в
Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=010f0000 ebx=00fe0838 ecx=0012f238 edx=00000000 esi=4015f03c edi=4015f040
eip=4000890a esp=0012f200 ebp=0012f220 iopl=0 nv up ei pl zr na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00010246
*** WARNING: Unable to verify checksum for C:\WINNT\System32\Vcl50.bpl
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINNT\System32\Vcl50.bpl -
Vcl50!System+8e:
4000890a ff5304 call dword ptr [ebx+0x4] ds:0023:00fe083c=????????
← →
Digitman (2003-09-23 17:11) [15]
> Ketmar
да уж)... на медленный газ ты сегодня тем паче не тянешь)
← →
Игорь Шевченко (2003-09-23 17:15) [16]Еще информация: call stack
WARNING: Stack unwind information not available. Following frames may be wrong.
Vcl50!System+0x8e
Vcl50!System+0x20
Vcl50!System+0xab
ntdll!LdrUnloadDll+0x315
ntdll!LdrQueryImageFileExecutionOptions+0x1616
ntdll!LdrLoadDll+0x16
kernel32!LoadLibraryExW+0x198
kernel32!LoadLibraryExA+0x5b
kernel32!LoadLibraryA+0xd
Vcl50!Stdctrls+0x71
Vcl50!Controls+0x124
Vcl50!Forms+0x3af
Vcl50!Controls+0x2f
Vcl50!Forms+0x1a
← →
mrcat (2003-09-23 17:17) [17]может Application.CreateHandle перед ExitCode?
← →
Думкин (2003-09-23 17:18) [18]У меня 6-й - здесь такого не наблюдаю.
← →
Digitman (2003-09-23 17:18) [19]
> Игорь Шевченко
похоже на то, что перехватчик искл-й потока (в SysInit) не подготовил стек к раскрутке ?
← →
Digitman (2003-09-23 17:21) [20]
> mrcat
какой Application ? не используется же модуль Forms
← →
Digitman (2003-09-23 17:22) [21]
> Думкин
уже что-то ...
а хост-приложение как собрано ? с RTP или без оных ?
← →
Думкин (2003-09-23 17:24) [22]Гы. Вылезло - тоже самое, когда с RTP собрал.
← →
Игорь Шевченко (2003-09-23 17:27) [23]Думкин © (23.09.03 17:24)
А, "...... мать", сказали сибирские мужики, после того, как положили лом в американскую лесопилку :))
← →
Digitman (2003-09-23 17:28) [24]
> Думкин
о как !
и Игорь тоже те же грабли поймал ... но на Д5 опять же ...
← →
Думкин (2003-09-23 17:28) [25]Вылетает только если оба собраны с RTP.
← →
Digitman (2003-09-23 17:34) [26]
> Думкин
> Вылетает только если оба собраны с RTP
ну практически так же и у меня
за исключением "run time error 217" при завершении хост-приложения ... ну это - из другой оперы, не суть как важно
← →
Игорь Шевченко (2003-09-23 17:35) [27]Ошибка происходит вот тут:
system.pas
procedure NotifyModuleUnload(HInstance: LongWord);
var
P: PModuleUnloadRec;
begin
P := ModuleUnloadList;
while P <> nil do
begin
try
P.Proc(HInstance);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
except
// Make sure it doesn"t stop notifications
end;
P := P.Next;
end;
end;
procedure UnregisterModule(LibModule: PLibModule);
var
CurModule: PLibModule;
begin
try
NotifyModuleUnload(LibModule.Instance);
^^^^^^^^^^^ а отсюда она вызывается ^^^^^^^^^^^^^^^^^^^^^
finally
if LibModule = LibModuleList then
LibModuleList := LibModule.Next
else
......
А UnregisterModule вызывается из Halt0
← →
clickmaker (2003-09-23 17:48) [28]А если DLL оформить так, AV не вылезает
library MyDLL;
uses SysUtils, Classes, Windows;
{$R *.RES}
procedure DLLMain(dwReason: cardinal);
begin
ExitCode := 1;
end;
begin
DLLProc := @DLLMain;
end.
← →
Digitman (2003-09-23 17:56) [29]
> clickmaker
потому что DllMain() не вызывается на этапе DLL_PROCESS_ATTACH
а при DLL_PROCESS_DETACH результат выполнения строчки ExitCode:=1 совершенно монопенисуален системе
← →
clickmaker (2003-09-23 18:02) [30]> Digitman © (23.09.03 17:56) [29]
Честно говоря, смысл такого кода
begin
ExitCode := 1;
end.
непонятен. Разве что, ради спортивного интереса... :)
← →
Игорь Шевченко (2003-09-23 18:03) [31]clickmaker © (23.09.03 18:02)
Отнюдь. Например, в некоторых случаях DLL не должна загружаться.
Просто убрана проверка на "некоторые случаи"
← →
Юрий Федоров (2003-09-23 20:09) [32]>>Отнюдь. Например, в некоторых случаях DLL не должна загружаться.
А может быть в случае сборки обоих модулей с RTP просто поднять исключение вместо ExitCode:=1?
Мне кажется, оно может быть отловлено в host"е ...
← →
Digitman (2003-09-24 08:09) [33]
> Юрий Федоров
> Мне кажется, оно может быть отловлено в host"е ...
И что же делать хост-процессу в этом случае, если он - non-Delphi ? Он же понятия не имеет ни о каких Делфи-исключениях !
← →
Alex Konshin (2003-09-24 09:16) [34]Кстати, не уверен. Механизм исключений поддерживается на уровне системы. Часто компиляторы изобретают свои механизмы исключений, но, по моему Delphi использует системный.
← →
Alex Konshin (2003-09-24 09:18) [35]Хотя это надо поисследовать, а они там такого понаворотили... Еще и linux под ногами путается.
← →
Игорь Шевченко (2003-09-24 10:02) [36]Alex Konshin © (24.09.03 09:16)
Угу, использует системный. Иначе бы Access Violation не перехватывался.
Юрий Федоров © (23.09.03 20:09)
В коране написано, что не очень хорошо возбуждать исключения в DLL и перехватывать их вне DLL. Но в любом случае будет возбуждаться исключение в загрузчике DLL, а чем это чревато, я, честно говоря, не знаю
← →
Владислав (2003-09-24 10:21) [37]> clickmaker © (23.09.03 18:02) [30]
На этапе загрузки DLL нужно, так сказать, препарировать ее состояние. По какой то причине, библиотека не в состоянии это сделать (нет необходимых ресурсов, не найдены необходимые файлы и прочее). Что же, грузить ее? На кой? Приложение все равно работать не будет. Хуже того, может работать неправильно. (Естественно, что это: ExitCode := 1 происходит по какому то условию).
> Digitman ©
Я подобное "ловил", но только без RTP. Установлена D6. При загрузке библиотеки производилась ее инициализация. Если она не успешная, изменялся ExitCode. Отладочная информация записывалась в лог-файл (Использовался модуль SysUtils). В итоге та же AV. Та же Run time error. Компилируешь с отключенной записью в лог файл - все происходит на ура.
← →
Игорь Шевченко (2003-09-24 12:10) [38]Владислав © (24.09.03 10:21)
И тому есть хорошее и доступное объяснение у Рихтера - на этапе инициализации DLL нельзя вызывать ряд функций :))
Страницы: 1 вся ветка
Форум: "Потрепаться";
Текущий архив: 2003.10.13;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.009 c