dll执行完后出错

peasy 2004-09-14 09:30:50
我写了一个返回字符串的涵数,放到DLL中!
我是这样调用的:

procedure TForm1.Button1Click(Sender: TObject);
Var MyProc: TMyproc;
MyHandle:THandle;
begin
MyHandle:=LoadLibrary ('dpubdll.dll') ;
If MyHandle<=0 then
Raise Exception.Create('动态链接库调用失败,错误代码是:'+Inttostr(Getlasterror))
else
@MyProc:=GetProcAddress(MyHandle,'SetPSW');
if not Assigned(MyProc) then
Raise Exception.Create('GetProcAddress调用失败,错误代码是:'+inttostr(getlasterror))
else
ShowMessage(MyProc('123456'));
Freelibrary(Myhandle); // 卸载DLL
end;

在关闭弹出的窗口后就出错了,去掉Freelibrary(Myhandle); 这句也出错!错误信息如下:
project tdll.exe raised exception class eaccessviolation with 'access violation at address 004003e82 in module 'tdll.exe'.read of address 01180ba4'. process stop .use step or run to continue
...全文
183 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
zzjzhao 2004-09-16
  • 打赏
  • 举报
回复
在动态链接库中不能使用string类型作为返回值
Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters.
荒原独歌 2004-09-16
  • 打赏
  • 举报
回复
已经改好发给你了
chinaandys 2004-09-16
  • 打赏
  • 举报
回复
begin
try
MyHandle:=LoadLibrary ('dpubdll.dll') ;
If MyHandle<=0 then
Raise Exception.Create('动态链接库调用失败,错误代码是:'+Inttostr(Getlasterror))
else
@MyProc:=GetProcAddress(MyHandle,'SetPSW');
if not Assigned(MyProc) then
Raise Exception.Create('GetProcAddress调用失败,错误代码是:'+inttostr(getlasterror))
else
ShowMessage(MyProc('123456'));
finally
Freelibrary(Myhandle); // 卸载DLL
end;
end;
看行不
peasy 2004-09-16
  • 打赏
  • 举报
回复
我已把程序发给你了yeti@seague.com

荒原独歌 2004-09-16
  • 打赏
  • 举报
回复
领分喽!
peasy 2004-09-16
  • 打赏
  • 举报
回复
怎么给分出错呀!
版主点办好丫!

TO:rabbit1125(兔子)
不好意思呀,我另外给你50分吧!
peasy 2004-09-15
  • 打赏
  • 举报
回复
我真的有改呀!
program tdll;

uses
ShareMem,
Forms,
testfu in 'testfu.pas' {Form1};

{$R *.res}

begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
荒原独歌 2004-09-15
  • 打赏
  • 举报
回复
绝对不可能出错的!
打开菜单 project -> View Source 看看你的工程文件改了吗?我把为什么出错的原理给你解释一下吧:

如果要给DLL传递的参数中有string也就是长字符串型的变量,那么一定要在各个.Dpr文件的uses子句的第一个位置加上sharemem,不然会出现“Access violation at 0x....”的错误。这是因为Delphi对长字符串采用了一种比较特殊的处理方式,Sharemem子句的作用是要保证在程序运行前要加载一个内存管理的DLL文件Borlndmm.dll(在Delphi 5以前的某些版本是Delphimm.dll,具体可见Sharemem.pas)。所以,用了Sharemem之后,如果要发行程序,还要把Borlndmm.dll或Delphimm.dll一同发行。
如果希望避免上面的这些麻烦,开发时可以用其他数据类型变通解决。而且,只要能保证字符串的长度不超过254个字符,也可以把string换成ShortString,上面的Sharemem就可省掉
peasy 2004-09-15
  • 打赏
  • 举报
回复
unit testfu;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TMyProc=function (strPSW:pchar):PChar;

TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
Var MyProc: TMyproc;
MyHandle:THandle;
ss:String;
begin
try
MyHandle:=LoadLibrary ('dpubdll.dll') ;
If MyHandle<=0 then
Raise Exception.Create('动态链接库调用失败,错误代码是:'+Inttostr(Getlasterror))
else
@MyProc:=GetProcAddress(MyHandle,'SetPSW');
if not Assigned(MyProc) then
Raise Exception.Create('GetProcAddress调用失败,错误代码是:'+inttostr(getlasterror))
else
ShowMessage(MyProc('abcdefg'));
finally
Freelibrary(Myhandle); // 卸载DLL
end;
end;

end.


to rabbit1125(兔子): 是不是这样!
执行弹出显示窗口后同样错的!
peasy 2004-09-15
  • 打赏
  • 举报
回复
library dpubdll;

uses
ShareMem,
SysUtils,
Classes,
strutils;
const SeekCON=64;
Seekgrp:array[0..31] of Word=
(12,32,45,56,
51,63,76,68,
89,96,97,36,
31,57,53,112,
230,214,114,50,
42,105,201,203,
21,28,206,43,
81,215,39,222);

{$R *.res}

function SetPSW(strPSW:PChar):PChar;stdcall;
begin
result:='asd';
end;



exports
SetPSW index 1;

begin
end.
荒原独歌 2004-09-15
  • 打赏
  • 举报
回复
你的程序我测过了,用我的方法可以!
peasy 2004-09-15
  • 打赏
  • 举报
回复
to rabbit1125(兔子): 你有无试过呀!

问题出在function SetPSW(strPSW:STring):STring;stdcall;声明!
改为function SetPSW(strPSW:pchar):pchar;stdcall;就可以了
表态调用是没事,
但是用动态调用总是出现pointer操作错误!

荒原独歌 2004-09-15
  • 打赏
  • 举报
回复
30分拿来!
荒原独歌 2004-09-15
  • 打赏
  • 举报
回复
//DLL工程文件
library dpubdll;

uses
ShareMem, //加在第一行!!!!
SysUtils,
Classes,
strutils;
const SeekCON=64;
Seekgrp:array[0..31] of Word=
(12,32,45,56,
51,63,76,68,
89,96,97,36,
31,57,53,112,
230,214,114,50,
42,105,201,203,
21,28,206,43,
81,215,39,222);

{$R *.res}
function SetPSW(strPSW:STring):STring;stdcall;
var i:Word;
begin
Result:='adf';
end;



exports
SetPSW index 1;

begin
end.

//下面你的代码是错误的
unit testfu;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,ShareMem;////××××兄弟,我让你是加在工程文件Program里。这里的ShareMem删掉!

//改为
program YourTestfu;

uses
ShareMem,//也是第一行!!!!!
Forms,
.....

unit testfu;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;////删掉ShareMem后
荒原独歌 2004-09-15
  • 打赏
  • 举报
回复
怎么可能?把你程序发给我:
yeti@seague.com
peasy 2004-09-14
  • 打赏
  • 举报
回复
unit testfu;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,ShareMem;

type
TMyProc=function (strPSW:STring):String;stdcall;

TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
Var MyProc: TMyproc;
MyHandle:THandle;
ss:String;
begin
try
MyHandle:=LoadLibrary ('dpubdll.dll') ;
If MyHandle<=0 then
Raise Exception.Create('动态链接库调用失败,错误代码是:'+Inttostr(Getlasterror))
else
@MyProc:=GetProcAddress(MyHandle,'SetPSW');
if not Assigned(MyProc) then
Raise Exception.Create('GetProcAddress调用失败,错误代码是:'+inttostr(getlasterror))
else
ShowMessage(MyProc('abcdefg'));
finally
Freelibrary(Myhandle); // 卸载DLL
end;
end;

end.
peasy 2004-09-14
  • 打赏
  • 举报
回复
library dpubdll;

uses
SysUtils,
Classes,ShareMem,
strutils;
const SeekCON=64;
Seekgrp:array[0..31] of Word=
(12,32,45,56,
51,63,76,68,
89,96,97,36,
31,57,53,112,
230,214,114,50,
42,105,201,203,
21,28,206,43,
81,215,39,222);

{$R *.res}
function SetPSW(strPSW:STring):STring;stdcall;
var i:Word;
begin
Result:='adf';
end;



exports
SetPSW index 1;

begin
end.
yangyugw 2004-09-14
  • 打赏
  • 举报
回复
library BG_Comm;

{$S-}
uses
SysUtils,
Classes,
Windows,
Read_meter in 'Read_meter.pas',
read_meter_interface in 'read_meter_interface.pas';

{$R *.res}


Procedure DLLEntryPoint(dwReason:DWord);
begin
Case dwReason of
DLL_PROCESS_ATTACH:bg_comm_Build;
DLL_PROCESS_DETACH:bg_comm_destroy;
DLL_THREAD_ATTACH:bg_comm_Build;
DLL_THREAD_DETACH:bg_comm_destroy;
end;
end;

exports
set_comm_para index 1, //设置参数
open_comm index 2, //打开串口
dial_connect index 3, //拨号连接
com_state_patrol index 4,//通讯状态侦测
Close_comm index 5, //关闭串口
hang_up index 6,//挂机
Get_comm_para index 7,//获得串口参数
send_instruct index 8;//发送指令
begin

DllProc:=@DLLEntryPoint;
DLLEntryPoint(Dll_PROCESS_ATTACH);
end.


以上是我写的动态连接库的工程代码
我分析错误可能发生在释放的地方,也可能是程序那里有问题,在释放或使用一个无效的
指针
wanwangzhiwang 2004-09-14
  • 打赏
  • 举报
回复
贴出代码来看看,可能有多种问题

1.看看两边函数是否对称的加上了safecall

2.看看是否有内存泄露
peasy 2004-09-14
  • 打赏
  • 举报
回复
TO:rabbit1125(兔子) 都是有问题:
project tdll.exe raised exception class einvalidpointer with message 'invalid pointer operation'.process stop. use stip or run to continue
加载更多回复(2)

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧