用DELPHI开发与ADO相关的DLL,编译DLL成功,但在主程序调用的时候却报错。反复排查,还没能解决错误里的非法指针的问题,因为非常急需,特请各位多多指点,谢谢!报错如下:
--------------------------------------
Project Project1.exe raised exception class EInvalidPointer with message 'Invalid pointer operation'.代码如下:
--------------------------------------
library mydb;
uses
base in 'base.pas';{$R *.res}exports OpenConn,getConn,CloseConn;begin
LibIni;
ExitProc := @LibExit;
end.unit base;
interface
uses
SysUtils, Classes, ActiveX, ADODB;procedure LibIni;
procedure LibExit;
procedure OpenConn();stdcall;
function getConn():TADOConnection;stdcall;
procedure CloseConn();stdcall;var
SaveExit:Pointer;
ADOConn: TADOConnection;
ConnectionString: String;
CommandTimeout: Integer;implementationprocedure LibIni;
begin
CoInitialize(nil);
ConnectionString := getStr('ConnectionString');
CommandTimeout := getInt('CommandTimeout');
SaveExit := ExitProc;
end;procedure LibExit;
begin
CoUninitialize;
ExitProc := SaveExit;
end;procedure OpenConn();stdcall;
begin
try
ADOConn := TADOConnection.Create(nil);
ADOConn.ConnectionString := ConnectionString;
ADOConn.CommandTimeout := CommandTimeout;
ADOConn.Connected := True;
ADOConn.Open;
except on E: Exception do
begin
ADOConn.Close;
ADOConn.Free;
end;
end;
end;function getConn():TADOConnection;stdcall;
begin
Result := ADOConn;
end;procedure CloseConn();stdcall;
begin
try
ADOConn.Connected := False;
ADOConn.Close;
ADOConn.Free;
ADOConn := nil;
except on E: Exception do
//
end;
end;end.
--------------------------------------
Project Project1.exe raised exception class EInvalidPointer with message 'Invalid pointer operation'.代码如下:
--------------------------------------
library mydb;
uses
base in 'base.pas';{$R *.res}exports OpenConn,getConn,CloseConn;begin
LibIni;
ExitProc := @LibExit;
end.unit base;
interface
uses
SysUtils, Classes, ActiveX, ADODB;procedure LibIni;
procedure LibExit;
procedure OpenConn();stdcall;
function getConn():TADOConnection;stdcall;
procedure CloseConn();stdcall;var
SaveExit:Pointer;
ADOConn: TADOConnection;
ConnectionString: String;
CommandTimeout: Integer;implementationprocedure LibIni;
begin
CoInitialize(nil);
ConnectionString := getStr('ConnectionString');
CommandTimeout := getInt('CommandTimeout');
SaveExit := ExitProc;
end;procedure LibExit;
begin
CoUninitialize;
ExitProc := SaveExit;
end;procedure OpenConn();stdcall;
begin
try
ADOConn := TADOConnection.Create(nil);
ADOConn.ConnectionString := ConnectionString;
ADOConn.CommandTimeout := CommandTimeout;
ADOConn.Connected := True;
ADOConn.Open;
except on E: Exception do
begin
ADOConn.Close;
ADOConn.Free;
end;
end;
end;function getConn():TADOConnection;stdcall;
begin
Result := ADOConn;
end;procedure CloseConn();stdcall;
begin
try
ADOConn.Connected := False;
ADOConn.Close;
ADOConn.Free;
ADOConn := nil;
except on E: Exception do
//
end;
end;end.
由於是採用dll的做法,所以TADOConnection的類型信息處於不同的地址空間,無法共享。
解決方式是在uses最前面加上sharemem
貌似多个DataSet共用另外一个模块的Connection的时候会冲突
建议模块间传个ConnectionString就够了,不要把对象传来传去
var
……
procedure OpenConn();stdcall; external 'mydb.dll';
function getConn():TADOConnection;stdcall; external 'mydb.dll';
procedure CloseConn();stdcall; external 'mydb.dll';implementation procedure TForm1.Button1Click(Sender: TObject);
var conn: TADOConnection;
begin
try
OpenConn();
conn := getConn();
CloseConn();
except on E: Exception do
//showmessage('wrong');
end;
end;
刚刚按你的指点在DLL和主程序的uses段的最前面加了sharemem,做测试,错误依旧啊.
主程序创建的对象只在主程序用,DLL创建的东西只在DLL里用就没事。
主程序和DLL要共享对象时尽量在主程序里创建,传pointer给DLL,完结时由主程序负责释放。
不知,你是不是把sharemem加在主程序和dll的工程文件中的uses段?要加在這裡才可以。
如果還不可以,建議把CoInitialize(nil); CoUninitialize; 這兩個方法去掉,看不出做com初始化有何意義?
sharemem确实加在DLL和主程序USES段的第一位,还是出同样错误,疑惑啊。
去掉CoInitialize(nil); CoUninitialize,在编译DLL的时候会提示什么没有初始化的错误,具体不记得了。TO:nhconch
本想把公用的写在DLL里,简化程序,现在的问题感觉写进DLL的作用不大,可能是我的技术水平有限吧,哎
不过建议你修改下程序,去掉LibExit函数,而采用在unit base的end.前加
initialization
CoInitialize;
Finalization
CoUninitialize;
来进行初始化和反初始化.
'Invalid pointer operation'错误好象是地址类型不匹配会出现的错误,在将一个堆内存地址指向栈内存地址时引起的错误就是'Invalid pointer operation'.
估计是你的ExitProc造成的.
你是在procedure LibExit;后面加 far 不报错还是去掉ExitProc调整后不报错的?我的错误是在退出的时候报错的,我用DELPHI7
已经发邮件给你,麻烦帮忙看看,谢谢!TO:fenger8293
1、其实之前我也试过在DLL的UNIT里加入
initialization
CoInitialize;
Finalization
CoUninitialize;
2、也试过用far,都是有错误的。
但是如果,有N个DLL模块需要调用处理数据库的DLL子模块,那不是会很麻烦?我想一定有解决的办法,可惜自己水平有限。
对于'Invalid pointer operation'错误应该是堆和栈内存指针混指的错误.
你可以仔细检查下自己的其他代码.看看getStr和getint有没有问题.
目前首要问题先推进项目进度,不过这个问题留着着实是个疙瘩。我喜欢完美:)
为了尽快解决这个问题,我在公司安装了DELPHI7来实时测试。
刚刚在libini里传了固定的值测试,还是一样,运行就没问题,只是在退出的时候还是出现相同错误。
这个问题就留做课题吧。
我打算把数据库处理的操作放在需要的DLL里,先把项目做完了。
我用你发给我的TEST文件重新编译,就又出现相同错误了。是我的DELPHI7有问题,还是我的系统有问题?
是呀,fenger8293 也是这么纠正的。
真的谢谢各位了!
估计我的系统不用重新安装了,哈哈,谢谢!