我有一个软件项目中,我有时从小型,简单的浮点运算得到奇怪的结果。我认为有件事我已经错过了,并想了解如何调试以下问题的一些提示:

(所使用的编译器是MS VC 6.0,也就是在Microsoft C编译器12版本)

第一个异常:

extern double Time, TimeStamp, TimeStep;  // History terms, updated elsewhere
void timer_evaluation_function( ) {
    if ( ( Time - TimeStamp ) >= TimeStep ) {  
        TimeStamp += TimeStep;  
        timer_controlled_code( );  
    }
{....}

出于某种原因,定时器评估失败,从不执行的定时码。在调试,没有问题地看到,TRIG条件实际上是真实的,但在FPU拒绝找到一个积极的结果。下面的代码段没有问题,但它执行相同的操作。这个问题,是通过将可能被允许失败的一个虚假的评价回避。

我猜FPU状态以某种方式由以前的操作进行污染,并有一些编译器标志,这将有助于?

第二异常:

double K, Kp = 1.0, Ti = 0.02;
void timed_code( ){
    K = ( Kp * ( float ) 2000 ) / ( ( float ) 2000 - 2.0F * Ti * 1e6 )
{....}

结果是#IND,即使在调试器评估方程至约0.05。当2.0F值被加载到FPU从使用FLD指令#IND值出现在FPU堆栈。先前指令将整型值2000作为使用FILD指令一个双浮动。一旦FPU堆栈包含#IND值全部丢失,但再次调试器没有问题评估公式。后来,这些操作返回预期的结果。

另外,再次在函数调用后直接发生FPU问题。我应当增加浮动,每个新的功能后,清除FPU状态点操作?是否有可能影响FPU以某种方式编译器标志?

我很感激在这一点上的任何和所有的技巧和窍门。

编辑:我已经成功通过调用函数顶部装配功能EMMS首先要避免这个问题。这样的FPU被清除,可能会或可能不会出现在我的代码是从所谓的环境中创建的任何MMX相关的垃圾。看来,FPU的状态是不是理所当然。

//弗兰克

有帮助吗?

解决方案

如果您正在使用Windows的QueryPerformanceCounter和QueryPerformanceFrequency的功能,支持MMX尝试查询频率/计数器后计算之前插入femms指令的系统上。

__asm femms

我已经在那里他们正在做使用MMX 64位计算,而不是清除浮点标志/状态之前碰到了麻烦,从这些功能。

如果在浮点操作之间存在任何64位算术这种情况可能也发生。

其他提示

不知道这个问题可能是什么,但在x86上,FINIT说明清除FPU。为了测试你的理论,你可以在你的代码中插入这个地方:

__asm {
    finit
}

这是不是一个真正的回答你的问题,但你可能想多看两眼Raymond Chen的关于奇怪的FPU行为的文章。看了你的问题,并重新阅读这些文章,我没有立即看到一个链接 - 但如果你已经粘贴的代码是不完整的,或者如果文章就给大家介绍这引起了一些问题,周围的行为的想法.. 。特别是,如果你加载任何地方附近的DLL。

未初始化浮点变量可以是致命的

怎么无效浮点运算异常引起人们的关注时,我禁用它?

虽然我不能为您提供一个确切的解决方案,我建议通过阅读的文章描述不同的优化可以使用。

重新:时间戳 -

什么是你让你的时间戳的来源?某事听起来可疑。试戴记录到一个文件中。

如果坏值通过应加载2.0 FLD加载,我会检查其中该值被从加载在存储器 - 它可能只是一个编译器/链接问题

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