gpt4 book ai didi

delphi - 为什么应用程序以不同于 Default8087CW 的 FPU 控制字启动?

转载 作者:行者123 更新时间:2023-12-03 14:40:30 27 4
gpt4 key购买 nike

您能否帮助我了解 Win32 平台上的 Delphi 应用程序中 FPU 控制字的情况。

当我们创建一个新的VCL应用程序时,控制字被设置为1372h。这是我不明白的第一件事,为什么它是1372h而不是1332h,这是在System单元中定义的Default8087CW

两者的区别:

1001101110010  //1372h
1001100110010 //1332h

是第 6 位,根据文档,它是保留或未使用的。

第二个问题涉及CreateOleObject

function CreateOleObject(const ClassName: string): IDispatch;
var
ClassID: TCLSID;
begin
try
ClassID := ProgIDToClassID(ClassName);
{$IFDEF CPUX86}
try
Set8087CW( Default8087CW or $08);
{$ENDIF CPUX86}
OleCheck(CoCreateInstance(ClassID, nil, CLSCTX_INPROC_SERVER or
CLSCTX_LOCAL_SERVER, IDispatch, Result));
{$IFDEF CPUX86}
finally
Reset8087CW;
end;
{$ENDIF CPUX86}
except
on E: EOleSysError do
raise EOleSysError.Create(Format('%s, ProgID: "%s"',[E.Message, ClassName]),E.ErrorCode,0) { Do not localize }
end;
end;

上述函数将控制字更改为137Ah,因此它打开了第3位(溢出掩码)。我不明白为什么它在之后调用 Reset8087CW ,而不是恢复进入函数之前的单词状态?

最佳答案

第 6 位被保留并被忽略。这两个控制字实际上是相等的,因为 FPU 的行为相同。系统恰好设置了保留位。即使您尝试将该值设置为 $1332,系统也会将其设置为 $1372。无论您要求第 6 位具有什么值,它总是会被设置。因此,在比较这些值时,您必须忽略这一点。这里没什么好担心的。

至于 CreateOleObject,作者决定,如果您要使用该函数,那么您也将在使用 COM 对象时屏蔽溢出,甚至超出范围。谁知道他们为什么这样做,而且只针对 32 位代码?可能他们发现了一堆经常溢出的 COM 对象,因此添加了这个膏药。在创建时屏蔽溢出是不够的,在使用对象时还需要完成,因此 RTL 设计者选择从此以后取消屏蔽溢出。

或者也许这是一个错误。他们决定不修复 32 位代码,因为人们依赖这种行为,但他们确实修复了 64 位代码。

无论如何,这个函数没有什么特别的作用。你不需要使用它。您可以编写自己的代码来执行您想要的操作。

使用互操作时,浮点控制是一个问题。 Delphi 代码需要未屏蔽的异常。使用其他工具构建的代码通常会掩盖它们。理想情况下,当您调用 Delphi 代码时会屏蔽异常,并在返回时取消屏蔽它们。预计其他库会任意更改控制字。另请注意,Set8087CW 不是线程安全的,这是 Embarcadero 多年来拒绝解决的一个大问题。

没有简单的前进之路。如果您没有在程序中使用浮点,那么您可以简单地屏蔽异常,并且可能没问题。否则,您需要确保在所有线程的所有点上正确设置控制字。一般来说,使用标准 Delphi RTL 几乎是不可能的。我个人通过用线程安全版本替换 RTL 的关键部分来处理这个问题。我已在此 QC 报告中记录了如何执行此操作:QC#107411

关于delphi - 为什么应用程序以不同于 Default8087CW 的 FPU 控制字启动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39684161/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com