调用dll时,提示错误:'Invalid pointer operation'?

解决方案 »

  1.   

    可是我把这段代码独立出去,不妨到dll中,执行是成功的!
    为什么?
      

  2.   

    具体原因不好说,是否接触DELPHI调用DLL不久?我想您如果能再看看DELPHI的书,对您有帮助。
      

  3.   

    你是不是在dll中使用了string又没有在项目中引用sharemem单元,你的参数传递方式是否设为stdcall的windows默认方式
      

  4.   

    我是没有引用sharemem单元,可我加上了也不行:(
    ‘的参数传递方式是否设为stdcall的windows默认方式’是什么意思?
    我在函数的调用中用了呀!dll的unit中的接口我也声明了!
      

  5.   

    我刚学delphi没多久,我现在很着急。。
      

  6.   

    要在dll和项目中都引用sharemem单元
      

  7.   

    我检查了一下,我进入dll重的函数没有包措,实在它中又调用了另一个函数,才会出现这种错误!
    是为什么?
      

  8.   

    hkbarton;好了,结果都有了!
    只是我在关掉窗体的时候报了同样的错误!这是什么原因?
      

  9.   

    还有你在dll中调用的什么函数?
      

  10.   

    我在dll的接口函数中又调用了一个dll的函数(怎么这么绕口:))
    我的意思是现在调用dll的功能都实现了,结果也得到了!
    只是关闭调用端的窗体时,提示了和刚才一样的错误!
    不知说清楚了没有?
      

  11.   

    如果你是动态的调用,应该在释放时用freelibrary释放
    你最好贴一写代码出来
      

  12.   

    我是静态的调用,因为我不太会用动态的!给你一些代码,麻烦你了!
    一、窗体端
     function DecryStrHex(StrHex, Key: string):string;stdcall;external 'Endry_pro.dll';
      function EncryStrHex(Str, Key: String): String;stdcall;external 'Endry_pro.dll';
      procedure libexit;stdcall;external 'Endry_pro.dll';
      var
      Form1: TForm1;
    implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);begin
     Edit4.Text:=EncryStrHex(Edit1.Text,Edit1.Text);
    end;
      

  13.   

    二、dll中
    unit Encry;
    interface
    uses sharemem,SysUtils;
    type
      TKeyByte = array[0..5] of Byte;
      TDesMode = (dmEncry, dmDecry);
      function EncryStrHex(Str, Key: String): String;stdcall;
      function DecryStrHex(StrHex, Key: String): String;stdcall;
    var
      subKey: array[0..15] of TKeyByte;   //存产生的16个密钥
    implementation
    function EncryStrHex(Str, Key: String):String;stdcall;
    var
      StrResult, TempResult, Temp: String;
      I: Integer;
    begin
      TempResult := EncryStr(Str, Key);
      StrResult := '';
      for I := 0 to Length(TempResult) - 1 do
      begin
        Temp := Format('%x', [Ord(TempResult[I + 1])]);
        if Length(Temp) = 1 then Temp := '0' + Temp;
        StrResult := StrResult + Temp;
      end;
      Result := StrResult;
    end;
    ///////////
    function EncryStr(Str, Key: String): String;
    var
      StrByte, OutByte, KeyByte: array[0..7] of Byte;
      StrResult: String;
      I, J: Integer;
    begin
    //判断明文长度是否大于零并且最后是否已null作为结束符
      if (Length(Str) > 0) and (Ord(Str[Length(Str)]) = 0) then
        raise Exception.Create('Error: the last char is NULL char.');
     //若密码的长度小于8,按标准加入符号
      if Length(Key) < 8 then
        while Length(Key) < 8 do Key := Key + Chr(0);
      while Length(Str) mod 8 <> 0 do Str := Str + Chr(0);
      //将前八位的位置记录下来,并取生成密钥
      for J := 0 to 7 do KeyByte[J] := Ord(Key[J + 1]);
      makeKey(keyByte, subKey);
      //产生玩16个密钥后开始加密数据
      StrResult := '';  for I := 0 to Length(Str) div 8 - 1 do
      begin
        for J := 0 to 7 do
          StrByte[J] := Ord(Str[I * 8 + J + 1]);
        desData(dmEncry, StrByte, OutByte);
        for J := 0 to 7 do
          StrResult := StrResult + Chr(OutByte[J]);
      end;  Result := StrResult;
    end;
      

  14.   

    只要你引用了sharemem单元,这段代码是看不出问题的,可能是其他地方的错
      

  15.   

    大概看了一下,大部分都是字符串的操作,如果不小心的话,即使结果正确也会出现指针越界的问题,错误应该在你的算法上,似乎和dll没有什么关系
      

  16.   

    那我要怎么改正?
    全部换成pchar?
    为什么代码不放入dll中时就没错?怎么办?
      

  17.   

    代码不放在dll中就没有错吗?那我建议你换成pchar了
      

  18.   

    可是若key定义成pchar,那这一句while Length(Key) < 8 do Key := Key + Chr(0);
    怎么写?
      

  19.   

    用setlength建立一个长为8的pchar,ptempchar
    if  strlen(key)<8 then StrCopy(ptempchar,key)
    //最后在把这个填充慢就可以了
      

  20.   

    //没有调试过
    var
     tempstring:pchar
    ...
    setlength(tempstring,8);
    ...
    if  strlen(key)<8 then 
    begin
     StrCopy(tempstring,key);
     for i:=strlen(ptempchar) to 7 do
      tempstring[i]:=chr(x);//注意这时你就不能填充#0了,因为会把它作为结束符
    end;
      

  21.   

    错! 错! 错!原因出在下面这一句:
       Result := StrResult;
    即在返回时返回一个字符串, 在动态库中不能这么做.原因很简单: 返回的字符串是在 Dll 中分配的, 在退出程序时, 主线程自动去释放字符串占用的内存空间, 而字符串的内存空间是属于 Dll 的, 这样就产生了地址越界释放的异常.
      

  22.   

    应该如此改:// 增加一个释放字符串指针的函数
    procedure DeleteStrPointer(AValue: PChar); stdcall;
    begin
       if Assigned(AValue) then
          try
             StrDispose(AValue);
          except
          end;
    end;function EncryStrHex(Str, Key: PChar): PChar; stdcall;
    begin
       // ... ...   // 返回动态分配的字符串
       result := StrNew(PChar(strResult));
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
       pchResult: PChar;
    begin
       pchResult := EncryStrHex(PChar(Edit1.Text), PChar(Edit1.Text));
       Edit4.Text := StrPas(pchResult);   // 别忘了调用释放字符串指针
       DeleteStrPointer(pchResult);
    end;
      

  23.   

    恩, kyee(浪子阿鹏) 说的有道理,我说错了
      

  24.   

    DeleteStrPointer(pchResult);是否可以用delphi的函数StrDispose(pchResult)
    procedure StrDispose(Str: PChar);
    begin
      if Str <> nil then
      begin
        Dec(Str, SizeOf(Cardinal));
        FreeMem(Str, Cardinal(Pointer(Str)^));
      end;
    end;
      

  25.   

    result := StrNew(PChar(strResult));使用 StrNew 分配的指针最好使用 StrDispose 来释放。倘若在 Button1Click 中直接调用 StrDispose(pchResult); 则会产生指针越界的错误,所以一定要放在 Dll 中去释放。