delphi – 由于更改了8087CW模式(png stretchblt),System.Move中
我有一个奇怪的记忆腐败问题。经过好几个小时的调试和尝试,我觉得我发现了一些东西。
例如:我做一个简单的字符串分配: sTest := 'SET LOCK_TIMEOUT '; 但是,结果有时会变成: sTest = 'SET LOCK'#0'TIMEOUT ' 所以_被替换为0字节。 当使用FPU堆栈(fild,fistp)进行快速存储器复制(在9到32个字节的情况下移动),System.Move函数中已经看到这种情况发生了一次(复制是非常棘手的,取决于时序): ... @@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:
好的,现在我发现为什么而不是什么时候! 我通过简单的检查改变了我的AsmProfiler的工作(所有功能都在进入和离开时被检查): if Get8087CW = $27F then //normally $1372? if MainThreadID = GetCurrentThreadId then //only check mainthread DebugBreak; 我“分析”一些单位和dll的和宾果(见堆栈): Windows.StretchBlt(3372289943,514,345,4211154027,13369376) pngimage.TPNGObject.DrawPartialTrans(4211154027,(0,0),(514,345))) pngimage.TPNGObject.Draw($7FF62450,345))) Graphics.TCanvas.StretchDraw((0,345)),$7FECF3D0) ExtCtrls.TImage.Paint Controls.TGraphicControl.WMPaint((15,0)) 所以发生在StretchBlt … 现在做什么?是Windows的错误还是PNG中的错误(包含在D2007中)? 注意:只是尝试重现不起作用: Set8087CW($27F); sSQL := 'SET LOCK_TIMEOUT '; 似乎更有异国情调…但是通过“Get8087CW = $ 27F”的debugbreak,我可以在另一个字符串中重现它: FPU第2部分: FPU第3部分: FPU决赛:腐败! 注2:也许FPU堆栈必须在System.Move中被清除? 解决方法
我没有看到这个特殊的问题,但如果FPU处于坏状态,Move肯定会被弄乱。思科的VPN驱动程序可以把事情搞砸,即使你没有做任何与网络有关的事情。
http://brianorr.blogspot.com/2006/11/intel-pentium-d-floating-point-unit.html http://www.dankohn.com/archives/343 http://blog.excastle.com/2007/08/28/delphi-bug-of-the-day-fpu-stack-leak/(Ritchie Annand的评论) 在我们的例子中,我们检测到错误的VPN驱动程序,并使用Delphi 7版本交换Move和FillChar,用Pascal版本替换IntToStr(Int64版本使用FPU),并且,由于我们使用FastMM,因此禁用其自定义固定因为它们比System.Move更容易受到影响。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |