用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.

解决方案 »

  1.   

    你應該是在調用getConn時出錯吧?
    由於是採用dll的做法,所以TADOConnection的類型信息處於不同的地址空間,無法共享。
    解決方式是在uses最前面加上sharemem
      

  2.   

    both add in application and dll 
      

  3.   

    测试getConn是成功的,并且做数据库查询、插入等操作也成功,就是在主程序退出时出现以上错误。
      

  4.   

    TADOConnection跨模块之间不要使用
    貌似多个DataSet共用另外一个模块的Connection的时候会冲突
    建议模块间传个ConnectionString就够了,不要把对象传来传去
      

  5.   

    因爲不知道你主程序是如何寫的,猜是資源釋放問題,所以建議加sharemem。從你的dll實現來看,dll上的對象的產生和銷毀都是由調用者控制。所以,如果加sharemem無效,就跟蹤你主程序調用到此dll的任何方法,並留意是何時釋放dll的
      

  6.   

    测试主程序调用如下(相关代码),请多多指教:……
    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;
      

  7.   

    即使在主程序里,不调用“CloseConn(); ”,还是会出相同错误。
      

  8.   

    叫你在主程序和dll中的uses語句段最前面加sharemem單元,有沒有加?試驗的結果如何?
      

  9.   

    不好意思啊,我白天在公司不写DELPHI,晚上回家才写.
    刚刚按你的指点在DLL和主程序的uses段的最前面加了sharemem,做测试,错误依旧啊.
      

  10.   

    如果你在DLL创建了对象供主程序用,在关闭时就报错的。应该避免这种做法。
    主程序创建的对象只在主程序用,DLL创建的东西只在DLL里用就没事。
    主程序和DLL要共享对象时尽量在主程序里创建,传pointer给DLL,完结时由主程序负责释放。
      

  11.   

    其實我始終認爲是沒有加sharemem的關係,因爲你在用dll中的對象的方法,可能產生字符串的傳遞。
    不知,你是不是把sharemem加在主程序和dll的工程文件中的uses段?要加在這裡才可以。
    如果還不可以,建議把CoInitialize(nil); CoUninitialize; 這兩個方法去掉,看不出做com初始化有何意義?
      

  12.   

    TO: Avan_Lau
    sharemem确实加在DLL和主程序USES段的第一位,还是出同样错误,疑惑啊。
    去掉CoInitialize(nil); CoUninitialize,在编译DLL的时候会提示什么没有初始化的错误,具体不记得了。TO:nhconch 
    本想把公用的写在DLL里,简化程序,现在的问题感觉写进DLL的作用不大,可能是我的技术水平有限吧,哎
      

  13.   

    這樣不是辦法,可否把你的code 發給我?我幫你看看 [email protected]
      

  14.   

    因为ADO用到了COM,所以要CoInitialize; CoUninitialize是肯定的.
    不过建议你修改下程序,去掉LibExit函数,而采用在unit base的end.前加
    initialization
       CoInitialize;
    Finalization
       CoUninitialize;
    来进行初始化和反初始化.
    'Invalid pointer operation'错误好象是地址类型不匹配会出现的错误,在将一个堆内存地址指向栈内存地址时引起的错误就是'Invalid pointer operation'.
    估计是你的ExitProc造成的.
      

  15.   

    我把你的代码copy过来好象没出错.要么你在procedure LibExit; 后面加far;试试
      

  16.   

    TO:fenger8293 
    你是在procedure LibExit;后面加 far 不报错还是去掉ExitProc调整后不报错的?我的错误是在退出的时候报错的,我用DELPHI7
      

  17.   

    TO:Avan_Lau
      已经发邮件给你,麻烦帮忙看看,谢谢!TO:fenger8293
    1、其实之前我也试过在DLL的UNIT里加入
    initialization 
      CoInitialize; 
    Finalization 
      CoUninitialize;
    2、也试过用far,都是有错误的。
      

  18.   

    我在想,我的项目比较小,到是可以把DLL处理数据库的操作放在主程序里。
    但是如果,有N个DLL模块需要调用处理数据库的DLL子模块,那不是会很麻烦?我想一定有解决的办法,可惜自己水平有限。
      

  19.   

    你忘記貼附件了吧,咋沒看到source?不會說是源碼太大被擋住了?
      

  20.   

    我copy你的程序,只是在libini里传了固定的值.运行没发现任何问题。
    对于'Invalid pointer operation'错误应该是堆和栈内存指针混指的错误.
    你可以仔细检查下自己的其他代码.看看getStr和getint有没有问题.
      

  21.   

    TO:Avan_Lau ,又发了一次,附件TEST.RAR。
    目前首要问题先推进项目进度,不过这个问题留着着实是个疙瘩。我喜欢完美:)
      

  22.   

    TO:fenger8293 
    为了尽快解决这个问题,我在公司安装了DELPHI7来实时测试。
    刚刚在libini里传了固定的值测试,还是一样,运行就没问题,只是在退出的时候还是出现相同错误。
      

  23.   

    TO:seekmydoom 
    这个问题就留做课题吧。
    我打算把数据库处理的操作放在需要的DLL里,先把项目做完了。
      

  24.   

    你把代码发到[email protected].去掉第三方组件.
      

  25.   

    好奇怪!
    我用你发给我的TEST文件重新编译,就又出现相同错误了。是我的DELPHI7有问题,还是我的系统有问题?
      

  26.   

    剛才看了你給我發代碼,發現你sharemem加錯地方,不是加在單元uses的最前面,而是工程文件(*.prj)uses段的第一段,修改后,運行沒錯誤。源代碼修改后,我會再發給你, 你自己在測試一下。
      

  27.   

    TO:Avan_Lau 
    是呀,fenger8293 也是这么纠正的。
    真的谢谢各位了!
      

  28.   

    建議你看一下dll工程文件中,最前面的那段英文註釋
      

  29.   

    非常感谢Avan_Lau、fenger8293 ,把ShareMem放在两个地方的最前面就OK了。
    估计我的系统不用重新安装了,哈哈,谢谢!