Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.09.11;
Скачать: CL | DM;

Вниз

Акцес виолейшен в длл   Найти похожие ветки 

 
Deep ©   (2005-08-16 17:53) [0]

в длл, ни с того ни с сего начала возникать ошибка на этой строчке

library mlib;
uses
ShareMem,
SysUtils,
Classes,
Controls,
Forms,
IniFiles,
......
var
IniFileName: string;
......

//вот здесь
IniFileName := ChangeFileExt(Application.ExeName, ".ini");

раньше работало нормально, а сейчас ошибка

в отладчике ExeName показывает имя именно приложения, а не длл, если написать
IniFileName := Application.ExeName + ".ini";
то ошибка(акцес виолейшен) пропадает.
Но тогда возникает ошибка в следующей(столь же банальной строке) строке

IniFile := TIniFile.Create(IniFileName);

это опять какая-то фигня с менеджерами памяти, хотя и в длл и в приложении я уже подключил ShareMem первым в списке.

Причем ситация все больше становится туманной ввиду того, что эта длл уже нормально работала. А перестала работать после того как я внес довольно таки много изменений в код приложения, правда этот измененный код ни коим образом не касается этой длл.

Возможно нужно еще включить какие-то дерективы?
Или увеличить стек?

ShareMem включен первым модулем в оба дпр-а(и приложение, и длл).


 
Eraser ©   (2005-08-16 18:00) [1]

Deep ©   (16.08.05 17:53)

Возможно объект Application для ДЛЛ не проинициализирован. Возникает ли ошибка если обратиться к другим полям Application?


 
deep ©   (2005-08-16 18:08) [2]


> в отладчике ExeName показывает имя именно приложения, а
> не длл, если написать
> IniFileName := Application.ExeName + ".ini";
> то ошибка(акцес виолейшен) пропадает.
> Но тогда возникает ошибка в следующей(столь же банальной
> строке) строке
>
> IniFile := TIniFile.Create(IniFileName);


 
deep ©   (2005-08-16 18:16) [3]

в длл используются модули

uses
 ShareMem,
 SysUtils,
 Classes,
 Controls,
 Forms,
 IniFiles,
 DB, DBTables, BDE;

а также используются глобальные переменные

var Database: TDatabase;
   Query: TQuery;
   QueryArray: array of TQuery;

указатели на TQuery используются в главной програме посредством экспортируемых функций типа:

function QueryOpen(s: PChar): TDataset;

адреса на которые приложение получает при загрузке длл.
Насколько я понял, при выполнении "слетает" стек(регистр esp) из-за непонятных проблем с управлением памятью. Но в чем же проблема конкретно - непонятно.


 
TUser ©   (2005-08-16 18:19) [4]

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


 
deep ©   (2005-08-16 18:38) [5]


> TUser ©

не первый год замужем. :))

Суть такова: из приложения нужно было вынести в длл работу с БДЕ(TDatabase, TQuery) и оставить только работу с результирующими наборами(TDataset). Что собственно я и сделал. В результате избавился в приложении от модуля dbtables и испульзую только db.
В длл используется и тот и другой. Пробовал однако добавть модуль dbtables в приложение -- проблемы не решает.

И еще в главном приложении часть констант оформил в секцию resorcestring. Возможно это тоже могло как то косвенно повлиять?

Все.


 
isasa ©   (2005-08-16 18:49) [6]

А не проще передавать параметром имя ini файла в процедуру(функцию) библиотеки, и не искать где чей  Application.
Что, кстати логичней.


 
deep ©   (2005-08-16 18:54) [7]


> isasa ©

если бы дело было именно в Application, я бы так и сделал. Но проблема более масштабная. Я могу закоментировать этот код вообще, ошибка лезет через пару строчек ниже.


 
Alexander Panov ©   (2005-08-16 18:59) [8]

deep ©   (16.08.05 18:54) [7]

Все же приведи побольше кода.

А еще подумай, может быть Application вовсе не создан объект в DLL?
Если надо получить имя пути, где находится DLL, используй такой метод:

function CPath: String;
var
   p: array[0..1024] of Char; // или [0..MAX_PATH+1]
   n: Integer;
begin
   n := GetModuleFileName(HINSTANCE,@p[0],1024);
   Result := "";
   if n>0 then
   begin
       SetLength(Result,n);
       Move(p[0],Result[1],n);
   end;
end;

...

   CGIPath := ExtractFilePath(CPath);


 
isasa ©   (2005-08-16 19:12) [9]

Выдержка из Delphi help-а


Global variables in a library
Global variables declared in a shared library cannot be imported by a Delphi application.

A library can be used by several applications at once,
but each application has a copy of the library in its own process space with its own set of global variables.
For multiple libraries--or multiple instances of a library--to share memory, they must use memory-mapped files.
Refer to the your system documentation for further information.

ИМХО. Убирать глобальные переменные

var Database: TDatabase;
  Query: TQuery;
  QueryArray: array of TQuery;


 
Юрий Зотов ©   (2005-08-16 19:12) [10]

> Deep

Попробуйте проинициалировать в DLL еще и глобальную переменную Session (значением из EXE).

Либо наооборот (если сессия открывается в DLL). В общем, Session при работе с BDE должен быть везде один и тот же (подобно Application и Screen).


 
Eraser ©   (2005-08-16 19:12) [11]

deep ©

Надо просматривать весь код, начиная с момента, который "инициирует" действия в [0].
Т.е. например инициатором может быть нажатие какой-то кнопки или реакция на какое-то событие, вам виднее.


 
deep ©   (2005-08-16 19:28) [12]


> isasa ©

в даном случае мне НЕ нужно чтоб это были действительно "глобальные переменные". Мне нужны именно копии этих переменных. Но суть не в этом, потому как длл будет юзать только одно приложение и доступ к этим переменным из других приложений(или копий этого приложения) впринципе не планируется.


> Юрий Зотов ©
> Попробуйте проинициалировать в DLL еще и глобальную переменную
> Session

весь фокус в том, что до работы с БДЕ в даном случае даже не доходит ход. Вначале в длл я считываю настройки из ини-файла(название базы данных, путь к файлам и т.п.)... вот тут то и подкашивает. Причем не на реальной ошибке, а из-за проблем с управлением памятью....


> Eraser ©   (16.08.05 19:12) [11]

ага, под отладчиком смотрел где вылетает... То что, на нормально написаной строке вылетает - это уже понятно. Смотрел регистры поцессора: видно как при каком-то из "call -$00006463" регистр ESP(стек) уходит за допустимые пределы. Вот почему?


 
deep ©   (2005-08-16 19:39) [13]

library paradox;
uses
 ShareMem,
 SysUtils,
 Classes,
 Controls,
 Forms,
 IniFiles,
 DB, DBTables, BDE,
 //ReestrUpd in "ReestrUpd.pas" {fmReestrUpd},
 PlugConfig in "PlugConfig.pas" {fmPluginConfig};

{$R *.res}

var Database: TDatabase;
   Query: TQuery;
   QueryArray: array of TQuery;

   IniFileName: shortstring;
   Initialized: boolean;
   optDatabase, optUsername, optPassword: string;

procedure PluginInit;
var IniFile: TIniFile;
const
   BdeError = "Не удается проинициализировать Borland Database Engine (BDE)!";
begin
 //проверим на работоспособность BDE
 if dbiInit(nil) <> DBIERR_NONE then
   Application.MessageBox(BdeError, "Ошибка");

{
 //если нужно, проапдейтим реестр(БДЕ)
 if not CheckUpdatedFlag then begin
   fmReestrUpd:= TfmReestrUpd.Create(Application);
   try
     fmReestrUpd.ShowModal;
   finally
     fmReestrUpd.Free;
   end;
 end;
}

 //инициализация плугина
 Database := TDatabase.Create(Application); //Application
 Database.Name := "Database";
 Database.DatabaseName := "dbDeepOWN";
 Database.LoginPrompt := false;
 Database.DriverName := "STANDARD";
 Database.Params.Values["DEFAULT DRIVER"] := "PARADOX";
 Database.Params.Values["ENABLE BCD"] := "FALSE";

// >>>>>>>>>>>>>>>> вылет идет вот здесь >>>>>>>>>>>>>>>>
 IniFileName := ChangeFileExt(Application.ExeName, ".ini");
 IniFile := TIniFile.Create(IniFileName);

 with Database do begin
   //читаем из ини-файла и присваиваем значения глобальным переменным
   optDatabase := IniFile.ReadString(PluginName, "Database", "");
   //формируем строку соединения
   Database.Params.Values["PATH"] := optDatabase;
   Open;
 end;

 Query := TQuery.Create(Application);
 Query.DatabaseName := Database.DatabaseName;

 Initialized := true;
end;

.....


 
Eraser ©   (2005-08-16 19:42) [14]

deep ©   (16.08.05 19:39) [13]
// >>>>>>>>>>>>>>>> вылет идет вот здесь >>>>>>>>>>>>>>>>


Дык ошибка тогда тут
Database.Params.Values["ENABLE BCD"] := "FALSE";


 
isasa ©   (2005-08-16 20:50) [15]

Зачем,

Database := TDatabase.Create(Application);
ведь можно
Database := TDatabase.Create(nil);

ведь совершенно очевидно, что освобождать придется ручками

Database.Close;
Database.Free;

Ведь совершенно очевидно, что Application содержит "левую" ссылку(не nil). Соглашусь на обратное, если кто-то укажет место, где она инициализируется правильным значением.


 
Slym ©   (2005-08-17 04:31) [16]

используются старые dcu- удали


 
deep ©   (2005-08-17 10:02) [17]


> Eraser ©   (16.08.05 19:42) [14]

Нет, и еще раз нет :))


> isasa ©
> Database := TDatabase.Create(Application);
> ведь можно
> Database := TDatabase.Create(nil);

согласен, поменял
теперь ошибка стала вываливыаться еще раньше,
на столь же безобидной функции

function PluginInfo: PChar;
begin
 PluginInfo := "Обеспечивает возможность работы клиента с таблицами базы Paradox (с использованием BDE).";
end;


> Slym ©

удалил, не помогает


 
Digitman ©   (2005-08-17 13:04) [18]


> ошибка стала вываливыаться


какая ошибка-то ?
гадать будем ?

уж 17 постов в дискуссии, а ТОЧНОЙ инф-ции об ошибке как не было так и нет ...


 
deep ©   (2005-08-17 14:35) [19]


>  Акцес виолейшен в длл [D7, WinXP]

а ошибка в сабже описана


 
Digitman ©   (2005-08-17 15:25) [20]


> ошибка в сабже описана


где ?


> возникает ошибка


> акцес виолейшен


ЭТО ты называешь "описанием ошибки" ?


 
deep ©   (2005-08-17 18:34) [21]

access violation at 0x0040c3d5: write of address  0x00030f4c

после поледних изменений в коде вываливается на повторном вызове экспортируемой функции

function PluginInfo: PChar;
begin
PluginInfo := "Обеспечивает возможность работы клиента с таблицами базы Paradox (с использованием BDE).";
end;


 
deep ©   (2005-08-17 19:34) [22]

если скомпилировать(и приложени, и длл) с runtime-пакетами, то ошибка немного модифицируется
access violation at adress xxxxxxxx in module dcc70.dll
Read of adress xxxxxxxx


 
Digitman ©   (2005-08-18 08:11) [23]


> access violation at 0x0040c3d5


собираешь exe-проект со всеми опциями встр.отладки, запускаешь из-под IDE, тут же вызываешь меню Search -> Find Error .., вводишь 0040c3d5 - и дебагер показывает тебе строчку твоего кода, при выполнении которой произошло исключение


 
sniknik ©   (2005-08-18 08:55) [24]

Digitman ©   (18.08.05 08:11) [23]
и это не поможет... ;)

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

(попытка обьяснить "плавающее" место глюка)

deep
проверь места где работаеш с динамическими переменными массивами, выделение памяти, "ранже чек еррор" проверку включи если выключал, и т.к. это dll то модели вызова процедур сравни в dll   и exe.

вот к примеру, работа с памятью
function PluginInfo: PChar;
begin
PluginInfo := "Обеспечивает возможность работы клиента с таблицами базы Paradox (с использованием BDE).";
end;
тип PChar, а где под него выделение памяти? куда запишется строка? проверь, замени все PChar на string, ShareMem ты все одно используеш. чего тогда "напрягаться" следить за PChar-ми.


 
evvcom ©   (2005-08-18 08:58) [25]

И еще. Автор, используя передачу объектов между exe и dll без компиляции с runtime packages, рискует нарваться на другие "абсолютно непонятные" ошибки. Имея две (или более :) )реализации классов, создавая объект одного класса, а обрабатывая его методами другого, где-нибудь в недрах vcl может встретить конструкцию вида if AnyObject is TAnyObject then и получить соответственно различные результаты при использовании и не использовании runtime packages. Почему-то на это никто не обращает внимания.


 
Digitman ©   (2005-08-18 09:07) [26]


> sniknik ©   (18.08.05 08:55) [24]


> тип PChar, а где под него выделение памяти?


она уже выделена - в секции инициализированных данных длл-модуля


 
--=ХР=--   (2005-08-18 10:50) [27]

function QueryOpen(s: PChar): TDataset;

Отстрел башки... Переписать все заново. И забыть о передаче объектов между разными исполняемыми модулями. Только простые типы данных. Или интерфейсы.


 
Slym ©   (2005-08-19 05:11) [28]

С рантаймами не пользуй шаремем.
И на кой тебе при шаремем и рантаймами PChar?
Открой окно CPU (Alt+Ctrl+C) и трасируй там, если в PluginInfo вызывается LStrClr - то все ясно



Страницы: 1 вся ветка

Текущий архив: 2005.09.11;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.025 c
4-1122015926
Gear
2005-07-22 11:05
2005.09.11
Имя запускаемого файла.


1-1123694728
Starcom
2005-08-10 21:25
2005.09.11
Как у MessageDlg сделать фон к примеру Белым?


14-1124125245
TJulia
2005-08-15 21:00
2005.09.11
Юниксовая аська


1-1124537780
Агент Х-СОМ
2005-08-20 15:36
2005.09.11
Отладка компонентов


3-1122525099
Ольга
2005-07-28 08:31
2005.09.11
Перевод пользовательской функции с T-SQL на PL/SQL