FastMM和动态加载js的DLL问题,怎么解决

 上传我的文档
 上传文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
delphi 内存管理及 fastmm 研究
下载积分:5000
内容提示:delphi 内存管理及 fastmm 研究
文档格式:DOC|
浏览次数:227|
上传日期: 20:15:01|
文档星级:
全文阅读已结束,如果下载本文需要使用
 5000 积分
下载此文档
该用户还上传了这些文档
delphi 内存管理及 fastmm 研究
关注微信公众号主要讨论VC++、Delphi语言在实际开发遇到的各种问题....
Delphi7 内存管理及 FastMM 研究 (对于EXE和DLL内存共享很有用)
[转] Delphi7 内存管理及 FastMM 研究 (对于EXE和DLL内存共享很有用)
发表于 19:34 浏览(32)
Delphi7 内存管理及 FastMM 研究[转]
作者:刘国辉
FastMM 是适用于delphi的第三方内存管理器,在国外已经是大名鼎鼎,在国内也有许多人在使用或者希望使用,就连 Borland 也在delphi2007抛弃了自己原有的饱受指责的内存管理器,改用FastMM.
但是,内存管理的复杂性以及缺乏 FastMM 中文文档导致国内许多人在使用时遇到了许多问题,一些人因此而放弃了使用,我在最近的一个项目中使用了FastMM,也因此遇到了许多问题,经过摸索和研究,终于解决了这些问题。
二、为什么要用FastMM
第一个原因是FastMM的性能接近与delphi缺省内存管理器的两倍,可以做一个简单的测试,运行下面的代码:
tic := GetTickC
for I := 0 to 100000 do
SetLength(S, I + 100);
edt1.Text := S;
SetLength(S, 0);
tic := GetTickCount - T
MessageDlg('Tic = ' + IntToStr(Tic), mtInformation, [mbOK], 0);
在我的IBM T23笔记本上,使用FastMM4(FastMM的最新版本)用时约为3300ms,而使用缺省的内存管理器,用时约为6200ms,FastMM4的性能提高达88%.
第二个原因FastMM的共享内存管理器功能使用简单可靠。当一个应用程序有多个模块(exe和dll)组成时,模块之间的动态内存变量如string的传递就是一个很大的问题,缺省情况下,各个模块都由自己的内存管理器,由一个内存管理器分配的内存也必须在这个内存管理器才能安全释放,否则就会出现内存错误,这样如果在一个模块分配的内存在另外一个模块释放就会出现内存错误。解决这个问题就需要使用到共享内存管理器,让各个模块都使用同一个内存管理器。Delphi缺省的共享内存管理器是BORLNDMM.DLL,这个内存管理器并不可靠,也常常出现问题,并且,在程序发布的时候必须连同这个DLL一起发布。而FastMM的共享内存管理器功能不需要DLL支持,并且更加可靠。
第三个原因是FastMM还拥有一些帮助程序开发的辅助功能,如内存泄漏检测功能,可以检测程序是否存在未正确释放的内存等。
三、出现什么问题
如果我们开发的应用程序,只有一个exe模块,那么,使用FastMM是一件非常简单的事情,只需要把FastMM.pas(最新版是FastMM4.pas)作为工程文件的第一个uses单元即可,如:
但是,通常情况下,我们的应用程序都是由一个exe模块加上多个dll组成的,这样,当我们跨模块传递动态内存变量如string变量时,就会出问题,比如,下面的测试程序由一个exe和一个dll组成:
// test.dll
FastMM4, …;
procedure GetStr(var S: const Len: Integer);
SetLength(S, Len); // 分配内存
FillChar(S[1], Len, ‘A’);
————————————————————————————————————-
program TestP
FastMM4, …;
//——————————————————
unit mM // 测试界面
procedure TForm1.btnDoClick(Sender: TObject);
for I := 1 to 10000 do
GetStr(S, I + 1);
edt1.Text := S;
Application.ProcessM
SetLength(S, 0);
当第二次执行btnDoClick过程时,就会出现内存错误,为什么这样?delphi的字符串是带引用计数的,跟接口变量一样,一旦这个引用计数为0,则会自动释放内存。在btnDoClick过程中,调用GetStr过程,用SetLength给S分配了一段内存,此时这个字符串的引用计数为1,然后执行edt1.Text := S语句,字符串的引用计数为2,循环再调用GetStr给S重新分配内存,这样原来的字符串的引用计数减1,再执行edt1.Text := S,原来的字符串引用计数为0,这时,就会被释放(注意,是在TestPrj.exe释放,而不是在Test.dll释放),但这时没有出错,当循环执行完毕之后,还有一个字符串的引用计数为2,但是执行SetLength(S,
0)之后,该字符串被edt1.Text引用,的引用计数为1,第二次执行btnDoClick时,执行edt1.Text := S时,上次的引用计数为1的字符串引用计数减一变为0,就会被释放,此时,会出现内存错误。
由此,可以看到,在另一个模块释放别的模块分配的内存,并不一定马上出现内存错误,但是,如果频繁执行,则会出现内存错误,这种不确定的错误带有很大的隐蔽性,常常在调试时不出现,但实际应用时出现,不仔细分析很难找到原因。
要解决这个问题,就要从根源找起,这个根源就是内存管理。
一、Delphi的内存管理
Delphi应用程序可以使用的有三种内存区:全局内存区、堆、栈,全局内存区存储全局变量、栈用来传递参数以及返回值,以及函数内的临时变量,这两种都是由编译器自动管理,而如字符串、对象、动态数组等都是从堆中分配的,内存管理就是指对堆内存管理,即从堆中分配内存和释放从堆中分配的内存(以下称内存的分配和释放)。
我们知道,一个进程只有一个栈,因此,也很容易误以为一个进程也只有一个堆,但实际上,一个进程除了拥有一个系统分配的默认堆(默认大小1MB),还可以创建多个用户堆,每个堆都有自己的句柄,delphi的内存管理所管理的正是自行创建的堆,delphi还把一个堆以链表的形式分成多个大小不等的块,实际的内存操作都是在这些块上。
delphi把内存管理定义为内存的分配(Get)、释放(Free)和重新分配(Realloc)。内存管理器也就是这三种实现的一个组合,delphi在system单元中定义了这个内存管理器TMemoryManager:
PMemoryManager = ^TMemoryM
TMemoryManager = record
GetMem: function (Size: Integer): P
FreeMem: function (P: Pointer): I
ReallocMem: function (P: P Size: Integer): P
由此知道,delphi的内存管理器就是一个 TMemoryManager 记录对象,该记录有三个域,分别指向内存的分配、释放和重新分配例程。
System单元还定义了一个变量 MemoryManager :
MemoryManager: TMemoryManager = (
GetMem: SysGetM
FreeMem: SysFreeM
ReallocMem: SysReallocMem);
该变量是delphi程序的内存管理器,缺省情况下,这个内存管理器的三个域分别指向GETMEM.INC中实现的SysGetMem、SysFreeMem、SysReallocMem。这个内存管理器变量只在system.pas中可见,但是system单元提供了三个可以访问该变量的例程:
// 读取内存管理器,也即读取MemoryManager
procedure GetMemoryManager (var MemMgr: TMemoryManager);
// 安装内存管理器(即用新的内存管理器替换缺省的内存管理器)
procedure SetMemoryManager (const MemMgr: TMemoryManager);
// 是否已经安装了内存管理器(即缺省的内存管理器是否已经被替换)
function IsMemoryManagerSet: B
四、共享内存管理器
什么是共享内存管理器?
所谓共享内存管理器,就是一个应用程序的所有的模块,不管是exe还是dll,都使用同一个内存管理器来管理内存,这样,内存的分配和释放都是同一个内存管理器完成的,就不会出现内存错误的问题。
那么如何共享内存管理器呢?
由上分析,我们可以知道,既然要使用同一个内存管理器,那么干脆就创建一个独立的内存管理器模块(dll),其他的所有模块都使用这个模块的内存管理器来分配和释放内存。Delphi7默认就是采取这种方法,当我们使用向导创建一个dll工程时,工程文件会有这样一段话:
{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. }
这段话提示我们,ShareMem 是 BORLNDMM.DLL 共享内存管理器的接口单元,我们来看看这个ShareMem,这个单元文件很简短,其中有这样的声明:
DelphiMM = 'borlndmm.dll';
function SysGetMem (Size: Integer): P
external DelphiMM name '@Borlndmm@SysGetMem$qqri';
function SysFreeMem(P: Pointer): I
external DelphiMM name '@Borlndmm@SysFreeMem$qqrpv';
function SysReallocMem(P: P Size: Integer): P
external DelphiMM name '@Borlndmm@SysReallocMem$qqrpvi';
这些声明保证了BORLNDMM.DLL将被静态加载。
在ShareMem的Initialization是这样的代码:
if not IsMemoryManagerSet then
InitMemoryM
首先判断内存管理器是否已经被安装(也即是否默认的内存管理器被替换掉),如果没有,则初始化内存管理器,InitMemoryManager也非常简单(把无用的代码去掉了):
procedure InitMemoryM
SharedMemoryManager: TMemoryM
// force a static reference to borlndmm.dll, so we don't have to LoadLibrary
SharedMemoryManager.GetMem:= SysGetM
MM: = GetModuleHandle (DelphiMM);
SharedMemoryManager.GetMem:= GetProcAddress (MM,'@Borlndmm@SysGetMem$qqri');
SharedMemoryManager.FreeMem:= GetProcAddress (MM,'@Borlndmm@SysFreeMem$qqrpv');
SharedMemoryManager.ReallocMem:= GetProcAddress (MM, '@Borlndmm@SysReallocMem$qqrpvi');
SetMemoryManager (SharedMemoryManager);
这个函数定义了一个内存管理器对象,并设置域指向Borlndmm.dll的三个函数实现,然后调用SetMemoryManager来替换默认的内存管理器。
这样,不管那个模块,因为都要将ShareMem作为工程的第一个uses单元,因此,每个模块的ShareMem的Initialization都是最先被执行的,也就是说,每个模块的内存管理器对象虽然不相同,但是,内存管理器的三个函数指针都是指向Borlndmm.dll的函数实现,因此,所有模块的内存分配和释放都是在Borlndmm.dll内部完成的,这样就不会出现跨模块释放内存导致错误的问题。
那么,FastMM又是如何实现共享内存管理器呢?
FastMM采取了一个原理上很简单的办法,就是创建一个内存管理器,然后将这个内存管理器的地址放到一个进程内所有模块都能读取到的位置,这样,其他模块在创建内存管理器之前,先查查是否有别的模块已经把内存管理器放到这个位置,如果是则使用这个内存管理器,否则才创建一个新的内存管理器,并将地址放到这个位置,这样,这个进程的所有模块都使用一个内存管理器,实现了内存管理器的共享。
而且,这个内存管理器并不确定是哪个模块创建的,所有的模块,只要将FastMM作为其工程文件的第一个uses单元,就有可能是这个内存管理器的创建者,关键是看其在应用程序的加载顺序,第一个被加载的模块将成为内存管理器的创建者。
那么,FastMM具体是如何实现的呢?
打开 FastMM4.pas(FastMM的最新版本),还是看看其Initialization部分:
{Initialize all the lookup tables, etc. for the memory manager}
InitializeMemoryM
{Has another MM been set, or has the Borland MM been used? If so, this file
is not the first unit in the uses clause of the project's .dpr file.}
if CheckCanInstallMemoryManager then
InstallMemoryM
InitializeMemoryManager 是初始化一些变量,完成之后就调用CheckCanInstallMemoryManager检测FastMM是否是作为工程的第一个uses单元,如果返回True,则调用InstallMemoryManager安装FastMM自己的内存管理器,我们按顺序摘取该函数的关键性代码进行分析:
{Build a string identifying the current process}
LCurrentProcessID: = GetCurrentProcessId;
for i := 0 to 7 do
UniqueProcessIDString [8 - i]:= HexTable [((LCurrentProcessID shr (i * 4)) and $F)];
MMWindow: = FindWindow ('STATIC', PChar (@UniqueProcessIDString [1]));
首先,获取该进程的ID,并转换为十六进制字符串,然后查找以该字符串为窗口名称的窗口。
如果进程中还没有该窗口,则MMWindow 将返回0,那就,就创建该窗口:
MMWindow: = CreateWindow ('STATIC', PChar (@UniqueProcessIDString [1]),
WS_POPUP, 0, 0, 0, 0, 0, 0, hInstance, nil);
创建这个窗口有什么用呢,继续看下面的代码:
if MMWindow && 0 then
SetWindowLong (MMWindow, GWL_USERDATA, Integer (@NewMemoryManager));
NewMemoryManager.Getmem: = FastGetM
NewMemoryManager.FreeMem: = FastFreeM
NewMemoryManager.ReallocMem: = FastReallocM
查阅MSDN可以知道,每个窗口都有一个可供创建它的应用程序使用的32位的值,该值可以通过以GWL_USERDATA为参数调用SetWindowLong来进行设置,也可以通过以GWL_USERDATA为参数调用GetWindowLong来读取。由此,我们就很清楚地知道,原来FastMM把要共享的内存管理器的地址保存到这个值上,这样其他模块就可以通过GetWindowLong来获读取到这个值,从而得到共享的内存管理器:
NewMemoryManager: = PMemoryManager (GetWindowLong (MMWindow, GWL_USERDATA)) ^;
通过上面的分析,可以看出,FastMM 在实现共享内存管理器上要比borland巧妙得多,borland的实现方法使得应用程序必须将BORLNDMM.DLL一起发布,而FastMM的实现方法不需要任何dll的支持。
但是,上面的摘录代码把一些编译选项判断忽略掉了,实际上,要使用FastMM的共享内存管理器功能,需要在各个模块编译的时候在FastMM4.pas单元上打开一些编译选项:
{$define ShareMM} //是打开共享内存管理器功能,是其他两个编译选项生效的前提
{$define ShareMMIfLibrary} //是允许一个dll共享其内存管理器,如果没有定义这个选项,则一个应用程序中,只有exe模块才能够创建和共享其内存管理器,由于静态加载的dll总是比exe更早被加载,因此,如果一个dll会被静态加载,则必须打开该选项,否则可能会出错
{$define AttemptToUseSharedMM} //是允许一个模块使用别的模块共享的内存管理器
这些编译选项在FastMM4.pas所在目录的FastMM4Options.inc文件中都有定义和说明,只不过这些定义都被注释掉了,因此,可以取消注释来打开这些编译选项,或者可以在你的工程目录下创建一个.inc文件(如FastShareMM.inc),把这些编译选项写入这个文件中,然后,在FastMM4.pas开头的“{$Include FastMM4Options.inc}”之前加入“{$include FastShareMM.inc}”即可,这样,不同的工程可以使用不同的FastShareMM.inc文件。
五、多线程下的内存管理
多线程环境下,内存管理是安全的吗?显然,如果不采取一定的措施,那么肯定是不安全的,borland已经考虑到这种情况,因此,在delphi的system.pas中定义了一个系统变量IsMultiThread,这个系统变量指示当前是否为多线程环境,那么,它是如何工作的?打开TThread.Create函数的代码可以看到它调用了BeginThread来创建一个线程,而BeginThread把IsMultiThread设置为了True.
再来看看GETMEM.INC的SysGetMem、SysFreeMem、SysReallocMem的实现,可以看到,在开始都由这样的语句:
if IsMultiThread then EnterCriticalSection(heapLock);
也就是说,在多线程环境下,内存的分配和释放都要用临界区进行同步以保证安全。
而FastMM则使用了一条CUP指令lock来实现同步,该指令作为其他指令的前缀,可以在在一条指令的执行过程中将总线锁住,当然,也是在IsMultiThread为True的情况下才会进行同步。
而IsMultiThread是定义在system.pas的系统变量,每个模块(exe或者dll)都有自己的IsMultiThread变量,并且,默认为Fasle,只有该模块中创建了用户线程,才会把这个变量设置为True,因此,我们在exe中创建线程,只会把exe中的IsMultiThread设置为True,并不会把其他的dll模块中的IsMultiThread设置为True,但是,前面已经说过,如果我们使用了静态加载的dll,这些dll将会比exe更早被系统加载,这时,第一个被加载的dll就会创建一个内存管理器并共享出来,其他模块都会使用这个内存管理器,也就是说,exe的IsMultiThread变量没有影响到应用程序的内存管理器,内存管理器还是认为当前不是多线程环境,因此,没有进行同步,这样就会出现内存错误的情况。
解决这个问题就是要想办法当处于多线程环境时,让所有的模块的IsMultiThread都设置为True,以保证不管哪个模块实际创建了内存管理器,该内存管理器都知道当前是多线程环境,需要进行同步处理。
还好,windows提供了一个机制,可以让我们的dll知道应用程序创建了线程。DllMain函数是dll动态链接库的入口函数,delphi把这个入口函数封装起来,提供了一个TDllProc的函数类型和一个该类型的变量DllProc:
TDLLProc = procedure (Reason: Integer); // 定义在system.pas
// 定义在sysinit.pas:
DllProc: TDllP
当系统调用dll的DllMain时,delphi最后会调用DllProc进行处理,DllProc可以被指向我们自己的TDllProc实现。而当进程创建了一个新线程时,操作系统会以Reason=DLL_THREAD_ATTACH为参数调用DllMain,那么delphi最后会以该参数调用DllProc,因此我们只要实现一个新的TDllProc实现ThisDllProc,并将DllProc指向ThisDllProc,而在ThisDllProc中,当收到DLL_THREAD_ATTACH时把IsMultiThread设置为True即可。实现代码如下:
OldDllProc: TDLLP
procedure ThisDllProc(Reason: Integer);
if Reason = DLL_THREAD_ATTACH then
IsMultiThread := T
if Assigned(OldDllProc) then
OldDllProc(Reason);
OldDllProc := DllP
DllProc := ThisDllP
ThisDllProc(DLL_PROCESS_ATTACH);
本文主要讨论了下面几个问题:
1、为什么要使用FastMM
2、跨模块传递动态内存变量会出现什么问题,原因是什么
3、delphi的内存管理和内存管理器是怎么回事
4、为什么要共享内存管理器,delphi和FastMM分别是如何实现内存管理器共享的
5、多线程环境下,内存管理器如何实现同步
6、多线程环境下,如何跨模块设置IsMultiThread变量以保证内存管理器会进行同步
要正确使用FastMM,在模块开发的时候需要完成以下工作:
1、打开编译选项{$define ShareMM}、{$define ShareMMIfLibrary}、{$define AttemptToUseSharedMM}
2、将FastMM(4).pas作为每个工程文件的第一个uses单元
3、如果是dll,需要处理以DLL_THREAD_ATTACH为参数的DllMain调用,设置IsMultiThread为True
七、参考文献
《Windows 程序设计第五版》[美]Charles Petzold著,北京大学出版社
《Delphi源代码分析》 周爱民 著,电子工业出版社
没有更多推荐了,怎么安装fastmm_百度知道
怎么安装fastmm
我有更好的答案
在 delphi 7 下使用
fastmm4 ,大致如下步骤:一、准备工作1、将文件 BorlndMM.dll,替换掉 Delphi/Bin 目录下的相应文件;2、设置路径:Enviroment-&Library-&Directories-& Library Path 添加FassMM路径(在Delphi安装目录下建立FastMM文件夹,“C:\Program Files\Borland\Delphi7\FastMM”,将FastMM4.pas、FastMM4Messages.pas、FastMM4Options.inc三个文件拷贝其中,添加库路径&$(DELPHI)/FastMM;&);二、使用在项目文件中(Project-&View Source打开),uses 后第一行添加FastMM4单元;例如:FastMM4,Main
‘Main.pas’
{MainForm},
三、选项FastMM4 有多种设置项,只需要修改 FastMM4Options.inc 文件即可,以下是常用的,更详细的请自行搜索:(1) 打开全调试模式,例:{$define
FullDebugMode}(2) 把FastMM_FullDebugMode.dll拷贝到编译后生成的可执行程序所在目录。(3) 打开内存泄漏报告:EnableMemoryLeakReporting(一般情况下是缺省打开的)。
为您推荐:
其他类似问题
您可能关注的内容
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。FastMM_FullDebugMode.dll 官方补丁
投诉建议:
千万流量共享 百度高权重排名
软件大小: 316KB
软件厂商:
软件语言: 简体中文
软件授权: 免费
软件评级:
应用平台:WinAll
更新时间:
编辑推荐:
本文件能够完美解决系统中缺失FastMM_FullDebugMode.dll文件等问题,太平洋下载中心提供FastMM_FullDebugMode.dll文件官方下载。使用前请详细阅读FastMM_FullDebugMode.dll丢失修复方法。
FastMM_FullDebugMode.dll使用方法:
方法一一、如果在运行某软件或编译程序时提示缺少、找不到FastMM_FullDebugMode.dll等类似提示,您可将从太平洋下载中心下载来的FastMM_FullDebugMode.dll拷贝到指定目录即可(一般是system系统目录或放到软件同级目录里面),或者重新添加文件引用。二、将软件包下载下来后,先将其解压(一般都是rar压缩包), 然后根据您系统的情况选择X86/X64,X86为32位电脑,X64为64位电脑。三、直接拷贝系统对应的FastMM_FullDebugMode.dll到系统目录里:&&&&1、Windows 95/98/Me系统,将FastMM_FullDebugMode.dll复制到C:\Windows\System目录下。 &&&&2、Windows NT/2000系统,将FastMM_FullDebugMode.dll复制到C:\WINNT\System32目录下。 &&&&3、Windows XP/WIN7/win10系统(64位系统对应64位dll文件,32位系统对应32位dll文件),将FastMM_FullDebugMode.dll复制到C:\Windows\System32目录下。 &&&&4、如果您的系统是64位的请将32位的dll文件复制到C:\Windows\SysWOW64目录。
四、打开"开始-运行-输入regsvr32 FastMM_FullDebugMode.dll",回车即可解决。希望太平洋下载中心为您提供的FastMM_FullDebugMode.dll对您有所帮助。
方法二 通过太平洋下载中心下载dll的朋友,可将下面的代码保存为“注册.bat“,放到dll文件同级目录(只要在同一个文件夹里面有这两个文件即可),双击注册.bat,就会自动完成FastMM_FullDebugMode.dll注册(win98不支持)。 下面是系统与dll版本对应的注册bat文件(64位的系统对应64位dll文件,32位系统对应32位的dll文件,如果64位的系统安装32位的dll文件,请将下面的system32替换为SysWOW64即可。) 复制代码代码如下: @echo 开始注册copy FastMM_FullDebugMode.dll%windir%\system32\ regsvr32 %windir%\system32\FastMM_FullDebugMode.dll /s @echo FastMM_FullDebugMode.dll注册成功 @pause
832.0KB|832.0KB|35MB|21.0KB|301.0KB|227.0KB|
聚超值推荐
今日更新推荐
软件分类目录
同类软件下载排行
热门关键词
为您推荐:调用Dll报写出错,请高手帮忙!
编辑:www.fx114.net
本篇文章主要介绍了"[推荐]
调用Dll报写出错,请高手帮忙!
20jakefj]",主要涉及到[推荐]
调用Dll报写出错,请高手帮忙!
20jakefj]方面的内容,对于[推荐]
调用Dll报写出错,请高手帮忙!
20jakefj]感兴趣的同学可以参考一下。
unit&Unit1;
&&Windows,&Messages,&SysUtils,&Variants,&Classes,&Graphics,&Controls,&Forms,
&&Dialogs,&StdCtrls,&ShellApi,&ShlO
&&TForm1&=&class(TForm)
&&&&Button1:&TB
&&&&procedure&Button1Click(Sender:&TObject);
&&&&{&Private&declarations&}
&&&&{&Public&declarations&}
&&Form1:&TForm1;
implementation
{$R&*.dfm}
Function&EnPassWord(PwdValue:&String):&Sexternal&'Login.dll';
procedure&TForm1.Button1Click(Sender:&TObject);
&&sPwdValue:&S
&&sPwdValue&:=&EnPassWord('AAA');
&&//showmessage(sPwdValue);
end.请使用ShareMem報什麼錯呢?
如果返回是&&參數是&String&&類型,最好調用者與DLL中都帶上&shareMem&&單元,
具體你看下生成DLL的說明。报写的地址出错.因为我没有调用过Dll,所以也不知道是哪出问题了.当在动态链接库中使用了长字符串类型作为函数的参数、变量或返回值时要应用ShareMem单元,而且必须是第一个被引用的单元。引用ShareMem单元了,运行时还是报write&address&'00XX...'出错
unit&Unit1;
&&Windows,&Messages,&SysUtils,&Variants,&Classes,&Graphics,&Controls,&Forms,
&&Dialogs,&StdCtrls,&ShellApi,&ShlObj,ShareM
&&TForm1&=&class(TForm)
&&&&Button1:&TB
&&&&procedure&Button1Click(Sender:&TObject);
&&&&{&Private&declarations&}
&&&&{&Public&declarations&}
&&Form1:&TForm1;
implementation
{$R&*.dfm}
Function&EnPassWord(PwdValue:&String):&Sexternal&'Login.dll';
procedure&TForm1.Button1Click(Sender:&TObject);
&&sPwdValue:&S
&&sPwdValue&:=&EnPassWord('AAA');
&&//showmessage(sPwdValue);
end.unit&Unit1;&
interface&
&&ShareMem,Windows,&Messages,&SysUtils,&Variants,&Classes,&Graphics,&Controls,&Forms,&
&&Dialogs,&StdCtrls,&ShellApi,&ShlO&
放到最前面。
DLL中也是。&不過你最好把DLL的單元也拿上來看下。&&ShareMem&must&be&the
&&first&unit&in&your&library's&USES&clause&AND&your&project's
program&Project1;
&&ShareMem,
&&Unit1&in&'Unit1.pas'&{Form1};
{$R&*.res}
&&Application.I
&&Application.CreateForm(TForm1,&Form1);
&&Application.R
end.上面的各位,问题是我只有dll文件没有代码,
是报这样的错:faulted&message:'Access&violation&at&0x7c957a50;write&of&address&0x0040d28'.process&stopped.&use&stop&or&runto&continue.。而且代码是这样的:
program&Project1;
&&ShareMem,
&&Unit1&in&'Unit1.pas'&{Form1};
{$R&*.res}
&&Application.I
&&Application.CreateForm(TForm1,&Form1);
&&Application.R
unit&Unit1;
&&Windows,&Messages,&SysUtils,&Variants,&Classes,&Graphics,&Controls,&Forms,
&&Dialogs,&StdCtrls,ShareMem{,&ShellApi,&ShlObj,ShareMem};
&&TForm1&=&class(TForm)
&&&&Button1:&TB
&&&&procedure&Button1Click(Sender:&TObject);
&&&&{&Private&declarations&}
&&&&{&Public&declarations&}
&&Form1:&TForm1;
implementation
{$R&*.dfm}
Function&EnPassWord(PwdValue:&String):&Sexternal&'Login.dll';
procedure&TForm1.Button1Click(Sender:&TObject);
&&sPwdValue:&S
&&sPwdValue&:=&EnPassWord('AAA');
&&showmessage(sPwdValue);
end.program&Project1;&
&&ShareMem,&
&&Unit1&in&'Unit1.pas'&{Form1};&
{$R&*.res}&
&&Application.I&
&&Application.CreateForm(TForm1,&Form1);&
&&Application.R&
unit&Unit1;&
interface&
&&Windows,&Messages,&SysUtils,&Variants,&Classes,&Graphics,&Controls,&Forms,&
&&Dialogs,&StdCtrls,ShareMem{,&ShellApi,&ShlObj,ShareMem};&
&&TForm1&=&class(TForm)&
&&&&Button1:&TB&
&&&&procedure&Button1Click(Sender:&TObject);&
&&private&
&&&&{&Private&declarations&}&
&&&&{&Public&declarations&}&
&&Form1:&TForm1;&
implementation&
{$R&*.dfm}&
Function&EnPassWord(PwdValue:&String):&Sexternal&'Login.dll';&
procedure&TForm1.Button1Click(Sender:&TObject);&
&&sPwdValue:&S
&&sPwdValue&:=&EnPassWord(PAnsiChar('AAA'));&
&&showmessage(sPwdValue);&
這樣試試。program&Project1;&
&&ShareMem,&
&&Unit1&in&'Unit1.pas'&{Form1};&
{$R&*.res}&
&&Application.I&
&&Application.CreateForm(TForm1,&Form1);&
&&Application.R&
unit&Unit1;&
interface&
&&Windows,&Messages,&SysUtils,&Variants,&Classes,&Graphics,&Controls,&Forms,&
&&Dialogs,&StdCtrls,ShareMem{,&ShellApi,&ShlObj,ShareMem};&
&&TForm1&=&class(TForm)&
&&&&Button1:&TB&
&&&&procedure&Button1Click(Sender:&TObject);&
&&private&
&&&&{&Private&declarations&}&
&&&&{&Public&declarations&}&
&&Form1:&TForm1;&
implementation&
{$R&*.dfm}&
Function&EnPassWord(PwdValue:&pAnsichar&):&Sexternal&'Login.dll';&&&
procedure&TForm1.Button1Click(Sender:&TObject);&
&&sPwdValue:&S
&&sPwdValue&:=&EnPassWord(PAnsiChar('AAA'));&
&&showmessage(sPwdValue);&
&用這個試下。或者,使用FastMM试试看还可以把参数类型改为PCahr试试看如果dll给出的形式就是
Function&EnPassWord(PwdValue:&String):&S&
那我劝你还是不要用了,dll的作者根本就不懂一个通用的dll该怎么设计To:Delphi(Pascal)&code
你好,我用你的代码原原本本考进去用还是报同样的错误,而且一运行就先把到
begin&--运行时先到这里,然后不管按F7,F8,F9哪一个来运行都马上报错.
Application.I&
所以我到现在还搞不清楚是哪出错了.把Login.dll发我邮箱:&&,我帮你看看。到网上下载个例子看看就知道了,还有直接插件式的调用范例。呵呵.To&xiaoxiao_8:
我已经传给你了。不用看了很简单,你的
Function&EnPassWord(PwdValue:&String):&Sexternal&'Login.dll';&
这句话路径不明确,你的这个工程与Login.dll肯定不在同一目录下,你把他们放在一个文件夹下,或者加上详细的路径名字。兄弟,你给我的Longin.dll文件装载不了。兄弟,你给我的Longin.dll文件装载不了。up该回复于 09:04:52被版主删除DING现在不知道还有多少人在用BCB,我用过两年,
你的问题应该不是DLL的问题,建议你断点调试,看具体是哪段代码有问题帮顶一个dll有源码不?
给我传个,我也试试!kjiwu_dll是不是VC或非Delphi写的呀。。
如果不是Delphi写的dll,请注意&调用约定和dll中函数名的问题。。由于编译器不同,形成dll的函数名还是不同的。。
可以使用微软的&Depends&查看一下函数名,之后在调用我觉得吧可以做一下尝试:
1.声明中的&string&改为PChar&试一下.
2.去掉stdcall&.
3.调用的时候不要使用'aaa'&而是使用变量传递.
写Dll返回String这种方式尽量避免使用.应该使用&参数传出结果最好.把&stdcall&改成cdecl&,string&改成&是不是DLL没放在同一个目录下.
一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!
二、互相尊重,对自己的言论和行为负责。
本文标题:
本页链接:}

我要回帖

更多关于 动态规划解决tsp问题 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信