Delphi。调用了一个自己写的Dll文件,执行都很正常,可在最后关闭的时候出错.Exception Einvalidpointer in Module.......
Dll是自己写的,用来封装数据库连接。只有一个Procedure dbconnect,其中就一个参数为database:Tdatabase.代码如下:
library Project1;uses
SysUtils,
dbtables,
Dialogs,
Classes;procedure dbconnect( database:tdatabase);stdcall;
begin
try
if database.Connected=true then
begin
database.Connected:=false;
end
else
begin
database.AliasName:='xx';
database.databasename:='xx';
database.loginprompt:=false;
database.Params.Values['USER NAME']:='admin';
database.params.values['PASSWORD']:='123';
database.Connected:=true;
end;
except on e:exception do
begin
showmessage(e.message);
end;
end;
end;exports dbconnect ;{$R *.RES}beginend.调用程序的源代码如下:
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Grids, DBGrids, Db, DBTables;type
TForm1 = class(TForm)
Database1: TDatabase;
DataSource1: TDataSource;
Query1: TQuery;
DBGrid1: TDBGrid;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;implementation{$R *.DFM}
procedure dbconnect(database:tdatabase);stdcall;external'Project1.dll'procedure TForm1.Button1Click(Sender: TObject);
begin
try
dbconnect(database1);
query1.Databasename:='xx';
datasource1.DataSet:=query1;
dbgrid1.DataSource:=datasource1;
with query1 do
begin
close;
sql.clear;
sql.Add('select * from x.hehe);
open;
end;
query1.Active:=true; except on e:exception do
begin
showmessage(e.message);
end;
end;
end;end. 以上程序运行OK。而且达到预期效果。只是当我关闭程序的时候竟然报错。Exception Einvalidpointer in Module Project1.exe 等等,后面是内存地址什么的。
我改换动态调用DLL的方法,依然报此错。很不解。
网上查了很久,没看到正解,只大概知道Einvalidpointer异常是发生在程序释放了已经释放过的对象的时候。疑惑啊。
是我传递database的问题吗?还是什么?
请知道的帮帮忙,谢谢啦。
Dll是自己写的,用来封装数据库连接。只有一个Procedure dbconnect,其中就一个参数为database:Tdatabase.代码如下:
library Project1;uses
SysUtils,
dbtables,
Dialogs,
Classes;procedure dbconnect( database:tdatabase);stdcall;
begin
try
if database.Connected=true then
begin
database.Connected:=false;
end
else
begin
database.AliasName:='xx';
database.databasename:='xx';
database.loginprompt:=false;
database.Params.Values['USER NAME']:='admin';
database.params.values['PASSWORD']:='123';
database.Connected:=true;
end;
except on e:exception do
begin
showmessage(e.message);
end;
end;
end;exports dbconnect ;{$R *.RES}beginend.调用程序的源代码如下:
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Grids, DBGrids, Db, DBTables;type
TForm1 = class(TForm)
Database1: TDatabase;
DataSource1: TDataSource;
Query1: TQuery;
DBGrid1: TDBGrid;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;implementation{$R *.DFM}
procedure dbconnect(database:tdatabase);stdcall;external'Project1.dll'procedure TForm1.Button1Click(Sender: TObject);
begin
try
dbconnect(database1);
query1.Databasename:='xx';
datasource1.DataSet:=query1;
dbgrid1.DataSource:=datasource1;
with query1 do
begin
close;
sql.clear;
sql.Add('select * from x.hehe);
open;
end;
query1.Active:=true; except on e:exception do
begin
showmessage(e.message);
end;
end;
end;end. 以上程序运行OK。而且达到预期效果。只是当我关闭程序的时候竟然报错。Exception Einvalidpointer in Module Project1.exe 等等,后面是内存地址什么的。
我改换动态调用DLL的方法,依然报此错。很不解。
网上查了很久,没看到正解,只大概知道Einvalidpointer异常是发生在程序释放了已经释放过的对象的时候。疑惑啊。
是我传递database的问题吗?还是什么?
请知道的帮帮忙,谢谢啦。
ActiveX;
initialization
CoInitialize(nil); finalization
CoUninitialize; 你试试看能行不?
initialization
CoInitialize(nil); finalization
CoUninitialize;
试试
还有,弱弱的问一下,这加在代码哪里啊?是DLL代码中?还是程序代码中?还有,具体能说下放到什么位置不?谢谢啦
Uses
ActiveX;
initialization
CoInitialize(nil); finalization
CoUninitialize;
uses
SysUtils,
dbtables,
Dialogs,
Classes,
ActiveX;------------------------------------------------
initialization
CoInitialize(nil);finalization
CoUninitialize;要写在你dll新建的一个单元文件中,
implementation{$R *.dfm}
这之后你试试看能解决你的问题么
CoInitialize(nil);finalization
CoUninitialize;end.
************************************************************
initialization —— 在单元中放在文件结尾前,包含用来初始化单元的代码,它在主程序运行前运行并且只运行一次。
finalization —— 在单元中放在 initialization 和 end. 之间,包含了单元退出时的代码。在程序退出时运行并且只运行一次。呵呵,大哥,小小纠正一下,以上才是加initialization 和finalization 的正解哦。在单元文件END前加。
还有啊,大哥,我感觉你的方法是有点道理的,但是,按照你的方法添加了代码之后,依然是那个错误。我很困惑。难倒你的方法是针对ADO控件才有用?DataAcess面板里头的Database控件用这个方法似乎是行不通。
既然Einvalidpointer异常是发生在程序释放了已经释放过的对象的时候。那么是否是,database在DLL中释放了,程序又释放一次FORM上的DATABASE呢?尴尬啊。我太菜了。
如能解决,感激涕零。
DATABASE1 := database; //其中,后面的参数是你主窗体传递过去的参数
在dll中一切的database操作都针对DATABASE1 而在:
initialization
CoInitialize(nil);finalization
CoUninitialize;
加入代码,修改如下:initialization
CoInitialize(nil);
DATABASE1 := TDataBase1.Create(nil);
finalization
DATABASE1.Free;
CoUninitialize;这样试试!
兄弟还是看一下程序再说啊,我没有返回字符串,DLL中是一个Procedure啊。
还有啊,加了ShareMem这个UNIT以后,程序就更加离谱了,不点Button也报那个错。之前还是运行BUTTON后才会报错啊。尴尬
我最开始就像想到可能是这个原因,可是我在关闭窗口事件里加上,database1.connected:=false来关闭连接,依然报错。
DATABASE1 := database; //其中,后面的参数是你主窗体传递过去的参数
在dll中一切的database操作都针对DATABASE1 而在:
initialization
CoInitialize(nil);finalization
CoUninitialize;
加入代码,修改如下:initialization
CoInitialize(nil);
DATABASE1 := TDataBase1.Create(nil);
finalization
DATABASE1.Free;
CoUninitialize;
--------------------------------------------------
其中的
initialization
CoInitialize(nil);
DATABASE1 := TDataBase1.Create(nil);
加在单元文件中有问题,database1是DLL中的啊,单元文件里头没有定义的吧。这是个问题,我把这个去掉,用你的思路,在DLL中创建DATABASE,依然是那个错误。
困惑。
诚然,正如兄弟所说,我给database里面赋值了,程序代码里给了,是password,username等,确实是字符串。学到了。谢谢指教。
但是,最关键的是,我按你的方法加ShareMem,在dll的Project文件,主程序的Project文件里加的。
可叹啊,不行。我感到费解。
问题解决。呵呵,大哥,我最欣赏你最后一句话。详细请自行查资料。
翻看资料,看到一句这样的话。
ShareMem must be the first unit in your library's USES class.
我太菜了,之前不知道要加第一个啊。得出结论了:ShareMem应加在Dll和主程序的project文件中,而且必须紧接在uses后的第一个位置引用,这是最关键的。如果说加错位置,那么就会产生一种有趣的现象:无论你是否调用DLL,退出程序都会报错。这也是新手常见问题啊。纸上得来终觉浅啊,后面啥来着?
感谢回答问题的大哥们。
结帐!!!!!!!!!!!!!