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的问题吗?还是什么?
  请知道的帮帮忙,谢谢啦。

解决方案 »

  1.   

    dll中封装ADO控件,需要在其单元文件中添加如下代码:Uses
       ActiveX;
    initialization 
    CoInitialize(nil); finalization 
    CoUninitialize; 你试试看能行不?
      

  2.   

    如上,加
    initialization  
    CoInitialize(nil);  finalization  
    CoUninitialize;
    试试
      

  3.   

    两位大哥,貌似database控件不属于ADO控件。
    还有,弱弱的问一下,这加在代码哪里啊?是DLL代码中?还是程序代码中?还有,具体能说下放到什么位置不?谢谢啦
    Uses
      ActiveX;
    initialization  
    CoInitialize(nil);  finalization  
    CoUninitialize; 
      

  4.   

    I'm Sorry!我没看清楚不过你还可以试试。ActiveX写在dll的Uses之后,如:
    uses
      SysUtils,
      dbtables,
      Dialogs,
      Classes,
      ActiveX;------------------------------------------------
    initialization
    CoInitialize(nil);finalization
    CoUninitialize;要写在你dll新建的一个单元文件中,
    implementation{$R *.dfm}
    这之后你试试看能解决你的问题么
      

  5.   

    initialization
    CoInitialize(nil);finalization
    CoUninitialize;end.
    ************************************************************
    initialization —— 在单元中放在文件结尾前,包含用来初始化单元的代码,它在主程序运行前运行并且只运行一次。
    finalization —— 在单元中放在 initialization 和 end. 之间,包含了单元退出时的代码。在程序退出时运行并且只运行一次。呵呵,大哥,小小纠正一下,以上才是加initialization 和finalization 的正解哦。在单元文件END前加。
    还有啊,大哥,我感觉你的方法是有点道理的,但是,按照你的方法添加了代码之后,依然是那个错误。我很困惑。难倒你的方法是针对ADO控件才有用?DataAcess面板里头的Database控件用这个方法似乎是行不通。
      既然Einvalidpointer异常是发生在程序释放了已经释放过的对象的时候。那么是否是,database在DLL中释放了,程序又释放一次FORM上的DATABASE呢?尴尬啊。我太菜了。
      如能解决,感激涕零。
      

  6.   

    这样看看行不行,在dll中定义一个DATABASE1,在dll的dbconnect函数中对其赋值:
    DATABASE1 := database;        //其中,后面的参数是你主窗体传递过去的参数
    在dll中一切的database操作都针对DATABASE1 而在:
    initialization
    CoInitialize(nil);finalization
    CoUninitialize;
    加入代码,修改如下:initialization
      CoInitialize(nil);
      DATABASE1 := TDataBase1.Create(nil);
    finalization
      DATABASE1.Free;
      CoUninitialize;这样试试!
      

  7.   

    EInvalidPointer不用看,%80楼主是跨DLL传了字符串引起的。主程序和DLL的项目文件第一个地方加上ShareMem试试吧。
      

  8.   

    LZ,最好不要用DLL传tdatabase对象,传connectstring就好。
      

  9.   


    兄弟还是看一下程序再说啊,我没有返回字符串,DLL中是一个Procedure啊。
    还有啊,加了ShareMem这个UNIT以后,程序就更加离谱了,不点Button也报那个错。之前还是运行BUTTON后才会报错啊。尴尬
      

  10.   


    我最开始就像想到可能是这个原因,可是我在关闭窗口事件里加上,database1.connected:=false来关闭连接,依然报错。
      

  11.   

    传字符串是包括对象中的字符串的,不要以为参数不是字符串类型就没事。你看看你那个dbconnect里面有没有给传入的对象设置过值(你没列出来我就不知道了)ShareMem是必须主程序和DLL的project文件都加的(注意是project文件,不是单元文件),你加好了吗?
      

  12.   

    这样看看行不行,在dll中定义一个DATABASE1,在dll的dbconnect函数中对其赋值:
    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,依然是那个错误。
    困惑。
      

  13.   

    传字符串是包括对象中的字符串的,不要以为参数不是字符串类型就没事。你看看你那个dbconnect里面有没有给传入的对象设置过值(你没列出来我就不知道了)ShareMem是必须主程序和DLL的project文件都加的(注意是project文件,不是单元文件),你加好了吗?----------------------------------------------------------------------------
      诚然,正如兄弟所说,我给database里面赋值了,程序代码里给了,是password,username等,确实是字符串。学到了。谢谢指教。
      但是,最关键的是,我按你的方法加ShareMem,在dll的Project文件,主程序的Project文件里加的。
    可叹啊,不行。我感到费解。
      

  14.   

    你不用改那么复杂,传对象也没问题。我就告诉你原理,你自己分析吧:DELPHI用字符串是以引用的方式保存的,一般情况下,在什么DLL(EXE)中“创建”(注意类比TInterfacedObject)这个字符串,就要在哪里释放这个字符串,否则就会由于找不到这个字符串的实际地址,从而导致EInvalidPointer的错误。从上述描述可以看出,不单是字符串作为显式调用时有这个问题,传对象时也有可能会有这个问题。然后你必须注意,我用的字眼是“可能”,也就是说,这决定于你这个字符串的引用是否被跨进程引用了,如果是的话,就会出错。要解决这个问题,第一种方法是避免这种情况,第二种方法是主程序和DLL都使用内存管理器,如ShareMem、FastMM等,详细请自行查资料。
      

  15.   


    问题解决。呵呵,大哥,我最欣赏你最后一句话。详细请自行查资料。
    翻看资料,看到一句这样的话。
    ShareMem  must be the first unit in your library's USES class.
    我太菜了,之前不知道要加第一个啊。得出结论了:ShareMem应加在Dll和主程序的project文件中,而且必须紧接在uses后的第一个位置引用,这是最关键的。如果说加错位置,那么就会产生一种有趣的现象:无论你是否调用DLL,退出程序都会报错。这也是新手常见问题啊。纸上得来终觉浅啊,后面啥来着?
    感谢回答问题的大哥们。
    结帐!!!!!!!!!!!!!