我有一个奇怪的内存损坏问题。经过几个小时的调试和尝试,我想我找到了一些东西。

例如:我做了一个简单的字符串赋值:

sTest := 'SET LOCK_TIMEOUT ';

然而,结果有时会变成:

sTest = 'SET LOCK'#0'TIMEOUT '

因此,_ 被替换为 0 字节。

我在 System.Move 函数中看到过这种情况发生一次(复制很棘手,取决于时间),当时它使用 FPU 堆栈(fild、fistp)进行快速内存复制(在移动 9 到 32 字节的情况下):

...
@@SmallMove: {9..32 Byte Move}
fild    qword ptr [eax+ecx] {Load Last 8}
fild    qword ptr [eax] {Load First 8}
cmp     ecx, 8
jle     @@Small16
fild    qword ptr [eax+8] {Load Second 8}
cmp     ecx, 16
jle     @@Small24
fild    qword ptr [eax+16] {Load Third 8}
fistp   qword ptr [edx+16] {Save Third 8}
...

使用 FPU 视图和 2 个内存调试视图(Delphi -> View -> Debug -> CPU -> Memory)我看到它出了问题......一次...但是无法重现...

今天早上我读到了一些关于 8087CW 模式的内容,是的,如果将其更改为 $27F,我会出现内存损坏!通常是$133F:

$133F 和 $027F 之间的区别在于 $027F 设置 FPU 进行不太精确的计算(限制为 Double 而不是 Extended)和不同的 Infiniti 处理(用于较旧的 FPU,但不再使用)。

好吧,现在我发现 为什么 但不是 什么时候!

我改变了我的工作方式 汇编分析器 通过简单的检查(因此在进入和离开时检查所有功能):

if Get8087CW = $27F then    //normally $1372?
  if MainThreadID = GetCurrentThreadId then  //only check mainthread
    DebugBreak;

我“分析”了一些单元和 dll 以及宾果游戏(参见堆栈):

Windows.StretchBlt(3372289943,0,0,514,345,4211154027,0,0,514,345,13369376)
pngimage.TPNGObject.DrawPartialTrans(4211154027,(0, 0, 514, 345, (0, 0), (514, 345)))
pngimage.TPNGObject.Draw($7FF62450,(0, 0, 514, 345, (0, 0), (514, 345)))
Graphics.TCanvas.StretchDraw((0, 0, 514, 345, (0, 0), (514, 345)),$7FECF3D0)
ExtCtrls.TImage.Paint
Controls.TGraphicControl.WMPaint((15, 4211154027, 0, 0))

所以它发生在 StretchBlt 中......

现在做什么? 这是 Windows 的错误,还是 PNG 的错误(包含在 D2007 中)?或者 System.Move 函数不是故障安全的?

笔记: 仅仅尝试重现是行不通的:

  Set8087CW($27F);
  sSQL := 'SET LOCK_TIMEOUT ';

好像比较有异域风情……但是通过“Get8087CW = $27F”上的 debugbreak,我可以在其他字符串上重现它:FPU 第 1 部分:FPU part 1FPU 第 2 部分:FPU part 2FPU 第 3 部分:FPU part 3FPU决赛:腐败!:FPU Final: corrupt!

笔记2: 也许必须在 System.Move 中清除 FPU 堆栈?

有帮助吗?

解决方案

我还没有看到这个特定的问题,但是移动绝对可以搞的一团糟,如果FPU是在一个糟糕的状态。思科的VPN驱动程序可以搞砸可怕的,即使你没有做任何与网络相关的。

HTTP://brianorr.blogspot的.com / 2006/11 / Intel的奔腾d-浮点unit.html [破]

HTTPS://web.archive .ORG /网络/ 20160601043520 / HTTP://www.dankohn.com/archives/343

HTTP: //blog.excastle.com/2007/08/28/delphi-bug-of-the-day-fpu-stack-leak/ (由里奇Annand评论)

在我们的例子中,我们检测车司机VPN和换出移动和FillChar与德尔福7版本,具有Pascal版本替换IntToStr(Int64的版本使用FPU),并且,因为我们使用的FastMM,我们禁用其定制固定大小的移动程序也一样,因为他们甚至比System.Move更敏感。

其他提示

这可能是视频驱动程序中的错误,导致在执行 StretchBlt 操作时不保留 8087 控制字。
过去,我在使用某些打印机驱动程序时也看到过类似的行为。他们认为自己拥有 8087 CW,但他们错了......

请注意,Delphi 中 8087 CW 的默认值似乎是 1372 美元;有关 CW 值的更详细说明,请参见 本文: :它还解释了 Michael Justin 在他的 8087CW 被冲洗时所描述的情况。

——杰罗恩

只是为了您的信息(在某些情况下,人有同样的问题太):我们做了我们的软件升级的客户,以及完整的触摸屏锁定时,我们的应用程序启动!窗户被完全冻结!计算机必须重新启动(断电)。它花了一些时间找出完全冻结的原因。

幸运我们在FastMove.LargeSSEMove的AV之一(仅1!)堆栈跟踪。我禁用SSE中fastmove使用,问题也没有了。

顺便说:触摸屏具有VIA尼CPU与芯片组S3

您不仅可以使用FPU,也完全冻结时,得到的内存损坏!

对于那些仍然有兴趣在这个:还有另一种可能引起的问题:

德尔福里约仍然船只与一个破碎的先进电子版本的 Move.

我有幸遇到的错误今天,幸运的是我有一个的可再现测试的情况。问题是这段代码:

* ***** BEGIN LICENSE BLOCK *****
 *
 * The assembly function Move is licensed under the CodeGear license terms.
 *
 * The initial developer of the original code is Fastcode
 *
 * Portions created by the initial developer are Copyright (C) 2002-2004
 * the initial developer. All Rights Reserved.
 *
 * Contributor(s): John O'Harrow
 *
 * ***** END LICENSE BLOCK ***** *)

// ... some less interesting parts omitted ...

@@LargeMove:
        JNG     @@LargeDone {Count < 0}
        CMP     EAX, EDX
        JA      @@LargeForwardMove

        // the following overlap test is broken
        // when size>uint(destaddr), EDX underflows to $FFxxxxxx, in which case 
        // we jump to @LargeForwardMove even if a backward loop would be appropriate
        // this will effectively shred everything at EDX + size
        SUB     EDX, ECX              // when this underflows ...
        CMP     EAX, EDX              // ... we also get CF=1 here (EDX is usually < $FFxxxxxx)
        LEA     EDX, [EDX+ECX]        // (does not affect flags)
        JNA     @@LargeForwardMove    // ... CF=1 so let's jump into disaster!

        SUB     ECX, 8 {Backward Move}
        PUSH    ECX
        FILD    QWORD PTR [EAX+ECX] {Last 8}
        FILD    QWORD PTR [EAX] {First 8}
        ADD     ECX, EDX
        AND     ECX, -8 {8-Byte Align Writes}
        SUB     ECX, EDX

参考文献

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top