相关疑难解决方法(0)

串联的Delphi字符串是否保存在保留对字符串的引用的隐藏临时变量中?

我试图了解Delphi服务器应用程序中的内存问题:最初我怀疑彻底泄漏,但是现在相信,由于编译器在使用+动态连接字符串时使用了隐藏的临时文件,因此内存的闲置时间比应有的更长。 ,造成痛苦的自由空间内存碎片。

背景:

这是Windows上的一整套32位服务器应用程序,Delphi版本已经很老了,我认为它是7,但可以肯定是Unicode之前的版本,并使用Nexus 3内存管理器在其中编写了DLL来挂接所有分配/ free调用(以及GB的内存跟踪)。

我有应用程序源代码,但没有编译器;我不是该应用程序的开发人员(甚至不是Delphi开发人员),但创建了广泛的自定义工具来监视,跟踪和分析内存。我一直在IDA Pro反汇编程序中选择.EXE。

一些示例代码:

我试图将这种情况减少到最低限度。此代码无意于编译:

procedure TaskThread.RunWorkLoop
begin
    while not Terminated do
    begin

      tsk := WaitForWorkToDo();  // this could sit for minutes at a time

      SetThreadName('Working on ' + tsk.Name);

      tsk.Run(); // THIS COULD TAKE A LONG TIME

      SetThreadName('Idle');
   end
end;
Run Code Online (Sandbox Code Playgroud)

SetThreadName() 接受一个const字符串参数并将其挂起,以便系统的其他部分知道此线程在做什么。

我对代码的反汇编显示,编译器已分配了一个隐藏的本地临时变量,以接收“工作中”部分和任务名称部分的串联,这是传递给的SetThreadName地方,它还保留了字符串的句柄。

当任务正在运行时-可能是20分钟-我相信该字符串有两个句柄。一个保存在内部SetThreadName,另一个保存在隐藏的临时文件中。

一切都很好。

然后,当任务结束且线程名称设置为时'Idle'SetThreadName()释放原始字符串并分配文字Idle

但是:我相信隐藏的本地临时文件仍然保留该字符串的句柄,且refcount = 1,因此它将占用空间,直到过程返回或下一循环来覆盖该隐藏的本地临时文件,释放旧值。

在此期间,程序无法访问它,无法将其显式释放,并且没有用处,但仍在消耗内存。

对于大多数过程而言,这无关紧要,因为它们的开始和结束都相对接近,因此所有内容都可以一次发布,但是在循环服务器应用程序中,这些过程可能会停留更长的时间。这导致我们内存碎片。

变得更糟

在实际的应用程序中,它更像是:

SetThreadName(tsk.Name + '-' + FormatDateTime('mm/dd/yy hh:nn:ss', Now)); …
Run Code Online (Sandbox Code Playgroud)

delphi string concatenation

10
推荐指数
1
解决办法
194
查看次数

标签 统计

concatenation ×1

delphi ×1

string ×1