Wod*_*dzu 11 delphi com fpu delphi-10.1-berlin
你能帮我理解在Win32平台上我的Delphi应用程序中FPU Control Word的运行情况.
当我们创建一个新的VCL应用程序时,控制字设置为1372h.这是我不明白的第一件事,为什么它是1372h而不是1332h,这是Default8087CW在System单位中定义的.
这两者之间的区别:
1001101110010 //1372h
1001100110010 //1332h
Run Code Online (Sandbox Code Playgroud)
是根据文档保留或不使用的第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;
Run Code Online (Sandbox Code Playgroud)
上面的功能是将控制字改为137Ah,所以它打开第3位(溢出掩码).我不明白为什么要调用它Reset8087CW,而不是恢复进入函数之前的单词状态?
第6位保留并被忽略.在FPU表现相同的意义上,这两个控制字实际上是相等的.系统恰好设置了保留位.即使您尝试将值设置为$1332,系统也会将其设置为$1372.无论你问第6位有什么价值,它总会被设置.因此,在比较这些值时,您必须忽略该位.这里没什么值得担心的.
至于CreateOleObject作者决定,如果你打算使用那个函数,那么你在使用COM对象时也会掩盖溢出,实际上超出了.谁知道他们为什么这样做,而且仅限32位代码?可能他们发现了一堆常常溢出的COM物体,因此添加了这种贴膏药.在创建时屏蔽溢出是不够的,在使用对象时也需要这样做.所以RTL设计者选择从今后取消屏蔽溢出.
或者这可能是一个错误.他们决定不为32位代码修复它,因为人们依赖于这种行为,但他们确实修复了64位代码.
无论如何,这个功能没有什么特别之处.您不需要使用它.你可以自己编写你想要它做的事情.
使用互操作时浮点控制是一个问题.Delphi代码需要未屏蔽的异常.用其他工具构建的代码通常会掩盖它们.理想情况下,当您调用Delphi代码并在返回时取消屏蔽它们时,您将屏蔽异常.期望其他库随意更改控制字.还要注意,这Set8087CW不是线程安全,这是Embarcadero多年来拒绝解决的一个大问题.
没有简单的方法.如果您没有在程序中使用浮点,那么您可以简单地屏蔽异常并且可能没问题.否则,您需要确保在所有线程中的所有点都正确设置控制字.通常,使用标准Delphi RTL几乎不可能.我个人通过用线程安全版本替换RTL的关键部分来处理这个问题.我已在此质量控制报告中记录了如何执行此操作:QC#107411.
| 归档时间: |
|
| 查看次数: |
590 次 |
| 最近记录: |