现在有一个这样的函数
function ReadIni(FileName,Section,Ident:string):string;stdcall;
是一个读文件的函数,返回的是字符串,上面的返回整型。
我用用样的方式调用它
.....
var 
  DLLHand:THandle;
  ReadIni:TReadIni;
...
function FileName:string;
begin
 Result:=ExtractFilePath(Application.ExeName) + 'MyConfig.INI';
end;function FileRead(FileName:string):string;
begin
  try
   DLLHand:=LoadLibrary('MyDLL.dll');
   @ReadIni:=GetProcAddress(DLLHand,'ReadIni');
   if @ReadIni <> nil then
      Result := ReadIni(FileName,'BDConn','DBFileName');
  finally
   FreeLibrary(DLLHand);//这里已经出过N次异常了,自己写的。我是仿照书上写的,书上这里始终没有出过异常,我这仿它写一次就出了异常。
  end;
end;异常提示:Exception:Debugger Fauilt Notification ....
          access violation at Ox0000000 read of address Ox00000000,我点了帮助,进去后,它给我的注意是:
你的程序中可能存在一个努力继续导致错误再次产生的一个混乱不整洁的状态,你可能需要中止应用程序调查这个异常的原由

解决方案 »

  1.   

    问题补充说明:
    我后来在uses那里加了一个ShareMem,这个在DLL的代码里也有,加上这个后就不会就那种异常了,但是新的异常又出现了。
    在我FreeLibrary之后,没有出现错误,当我关闭这个应用程序后,就提示了一个EInvalidPointer的异常,我也不知道是什么原因导致的,然后我再继续运行就弹出一个错误
    Runtime error at 217 at 00401276,好像在关闭应用程序后才弹出。
    这个问题已经3个月没有解决了,现在解决了一半了,这些代码都是自己敲的,仿照书上敲的,书里有个光盘,那个上面的代码和我写的是一模一样,就是变量名称不一样,书上的代码怎么执行都没有异常的。
      

  2.   

    function ReadIni(FileName,Section,Ident:string):string;stdcall; 不是必要的话,返回值是pchar就可以了
      

  3.   


    function FileRead(FileName:string):string;
    type
      IReadIni = function(FileName,Section,Ident:string):string;
    var MyReadIni:IReadIni;
    begin 
      try 
      DLLHand:=LoadLibrary('MyDLL.dll'); 
      @MyReadIni:=GetProcAddress(DLLHand,'ReadIni'); 
      if @ReadIni <> nil then 
          Result := MyReadIni(FileName,'BDConn','DBFileName'); 
      finally 
        FreeLibrary(DLLHand); 
      end; 
    end; 
    另外,不要让DLL函数返回string类型,通常用PChar类型作输入输出参数。
      

  4.   

    用了string就要uses sharemem单元
      

  5.   

    我就是按5楼说的,我用了ShareMem,所以就用了string
    还有,现在的问题是EInvalidPoint这个是string导致的吗?
    为什么后来又有Runtime error 217 at 0041278
    这个不是什么217-C不支持吗?我不是不想用PChar,是因为有一个函数ExtractFilePath()这个是返回string型的,这个函数是要在DLL的函数里调用,如果改城PChar就会说类型不一致,什么PChar和string的什么错误
      

  6.   

    返回值不能用PChar,如果你不想uses ShareMem,又要返回字符串,应该要增加两个参数,一个是字符串缓冲区指针,一个是缓冲区大小。
    ShareMem要放到dpr的第一个引用的单元,否则退出时会报错,因为内存管理器没有最先被替换。
      

  7.   

    ShareMem,我在每一个自己写的单元里都加了,我都加上了还是有异常。
      

  8.   

    ShareMem要放到dpr的第一个引用的单元,否则退出时会报错,因为内存管理器没有最先被替换。
      

  9.   

    ShareMem,我在每一个自己写的单元里都加了
    你说的第一个单元是哪个单元?是系统的还是我自己写的?
    ShareMem,我在每一个自己写的单元里都加了ShareMem,我在每一个自己写的单元里都加了ShareMem,我在每一个自己写的单元里都加了
    如果这些还不对就要在所有系统的单元里加了!
      

  10.   

    program Project1;uses
      ShareMem, //放到这
      Forms,
      Unit1 in 'Unit1.pas' {Form1};这才是dpr文件(项目文件)
      

  11.   

    11楼的兄弟,我加过了,都加了,就差系统的PAS里面没有加了,可还是相同的异常的。你们说的我肯定马上都加,而且是一点不漏的加上
      

  12.   

    是不是你的dll的问题,你在dll里面加个退出函数算了
    library Mydll
    uses Sharemem,...;
    procedure xxxx...
    exports
      xxxxbegin
      @dllproc:=....
    end;
      

  13.   

    procedure WriteIni(FileName,Main,Key,Values:PString);
    var
      WIni :TIniFile;//定义一个对象
    begin
      WIni :=TIniFile.Create(string(FileName));//创建这个对象
      try
        WIni.WriteString(PString(Main),PString(Key),PString(Values));//开始写入文件
      except
        ShowMessage('文件写入错误!请检查文件位置是否正确。');
      end;
      WIni.Destroy;
    end;
    function ReadIni(FileName,Main,Key:PString):PString;
    var
      RIni :TIniFile;
    begin
      RIni :=TIniFile.Create(FileName);      
      try
        Result :=PString(RIni.ReadString(PString(Main),PString(Key),PString('')));
      except
        ShowMessage('文件读取错误!请检查文件位置是否正确。');
      end;
      RIni.Destroy;
    end;
    procedure DeleteIni(FileName,Main,Key:PString);
    var
      DIni :TIniFile;
    begin
      DIni :=TIniFile.Create(FileName);
      try
        DIni.DeleteKey(PString(Main),PString(Key));
      except
        ShowMessage('删除文件错误!');
      end;
      DIni.Destroy;
    end;
    end.
    你们自己看,我是不是没有进行强制转化之类的,我都转化了,但是编译不通过
    [Error] Common.pas(20): Incompatible types: 'String' and 'PAnsiString'
    这个错误有10多个,别说我没有基础什么的,我不是不知道转化,还有!你们说的那个PChar,这是什么?在字符,我要返回的是字符串,我想PChar返回的应该不多。就用的PString,这个类型D7应该认识了吧。我后来测试了PChar,一个数据库连接字符串到PChar那出来就剩10多个字符了,什么uid什么pwd都没有读到;
    这里ReadString和WriteString这些函数里它本身就是要求是string类型的,函数体里面是对这些string参数用PChar转化的
    procedure TIniFile.WriteString(const Section, Ident, Value: string);
    begin
      if not WritePrivateProfileString(PChar(Section), PChar(Ident),
              PChar(Value), PChar(FFileName)) then
        raise EIniFileException.CreateResFmt(@SIniFileWriteError, [FileName]);
    end;
    我在这里不用String用什么?这个函数是必须要用的。我一用PChar或者是PString就说两个类型不一致 
      

  14.   

    没人告诉你要每个单元都加,DLL和EXE都要加上,只要加在dpr文件中,但一定要是uses中的第一个单元。你不要老强调你加没加,不是加没加的问题,是位置的问题。
      

  15.   

    我只在dpr里和DLL的dpr里加了ShareMem,其他里面的我都删除了。可是还是有异常的,那个异常是我永远的痛!一辈子就别想扔掉
      

  16.   

    感谢各位高手帮忙,小弟又会了新的知识!谢谢!我现在不仅能用ShareMem还可以不用它,直接用PChar都不出问题的!一下学会了两种DLL写法!
      

  17.   

    看起来没问题不代表真没问题,直接返回PChar不一定正确
      

  18.   

    如果返回PChar不正确的话,那直接返回string就要加上ShareMem的,但是这样做的话,这个DLL只能是DELPHI调用它不出问题,别的语言调用它就会很麻烦,ShareMem是针对DELPHI而存在的,如果你的程序和DLL里都有ShareMem,那么别的语言就不方便去访问DLL了,至少会有很多的异常。DLL是所有WIN32程序都会调用的,就是说DLL是不分语言的,如果MS公司做的操作系统中的DLL不支持访问BORLAND中的程序或者DLL,那么BORLAND又怎么能出的来?这样就是说DLL不能限定死是只有哪个语言才能访问的,是所有语言都能访问才对。
      

  19.   

    动态库函数不应该出现string类型,要用pchar代替。
      

  20.   

    现在出来一个新的问题,就是我写了有3-4个函数是静态调用的,不是动态的
    function SQLDataSet(sqlText:string,ADOConn:TADOConnection):TDataSet;stdcall;extrnal 'SQLHandle.dll';
    就像这样调用的函数,静态调用怎么出现了错误?
    EAccessViolation,我不知道是为什么,我也在DLL里最前面添加了ShareMem了,应用程序中也添加过了ShareMem,不知道为什么会出错。