未初始化的浮点变量,再现不确定的行为

Uninitialized floating point variables, repoducing indeterminate behavior

本文关键字:不确定 初始化 浮点变量      更新时间:2023-10-16

我必须调试一些显示瞬时和零星行为的代码,这最终可能归因于初始化行中未初始化的float,即:

float a = number, b, c = other_number;

这段代码通过串行连接快速采样设备,并在一定间隔内平均输出。每隔一段时间,会报告数字2.7916085e+035,但否则代码按预期工作,并且错误不可重现。

由于数字总是2.7916085e+035,我认为可能有一些问题与通信处理,或设备本身,但这些被排除。我几乎准备把它归咎于外部干扰,直到我终于在调试器中发现了一个错误的样本。

那么,回答这个问题。有人可以假设2.7916085e+035的意义吗?我不确定它在我的语境之外有什么意义,但让我困扰的是这个数字本质上是不可复制的可复制的。也就是说,我不能可靠地复制这个问题,但当它出现时,它总是一样的。从我的理解,未初始化的变量应该是不确定的。值得注意的是,问题发生在程序执行的所有不同位置、阶段、时间等。但总是在同一个系统上。

是。net框架、运行时或操作系统中的某些东西导致了这种行为吗?这是特别麻烦的跟踪,因为未初始化的变量总是具有相同的值,当它没有被幸运地设置为0时。

编辑:一些上下文。代码位于计时器内,计时器具有可变的滴答率,因此变量是类的局部非静态成员:

if(//some box checked)
{
    switch(//some output index)
    {
        case problem_variable:
        {
            if(ready_to_sample)
            {
               float average;
               for each(float num in readings)
               {
                 average += num;
               }
               average /= readings.Count;
            }
         }
    }
}

这里的变量是averagereadings是我想求平均值的输出列表。average将在每个....中重新声明一次平均值,可以以秒、分、小时或任何满足取平均值条件的时间为单位。该变量通常会得到0,但偶尔也会得到上面的数字。

在常见的浮点编码中,2.7916085e+035是0x7a570ec5作为浮点数,0x474ae1d8a58be975作为双精度,模端序。它们看起来不像典型的文本字符串、简单整数或普通地址。(双位数编码的低位是不确定的,因为你没有捕获足够的十进制数字来确定它们,但是高位看起来没有意义。)

64位二进制中的double转换成

0100011101001010111000011101100010100101100010111110100000000000

01111010010101110000111011000101

为32位浮点数。几乎所有现代处理器都将指令和数据分开——尤其是R/W数据。当然,旧的x86是例外,它是一种CISC处理器,基于4004处理器,那时每个字节都很宝贵,甚至小型计算机也没有缓存可以使用。然而,在现代操作系统中,更有可能的情况是,在移动4或8KB的页面时,更改了一页指令,而没有将旧页面清零。

双版本可能相当于

Increment by 1, where r7 (EDI - extended destination index) is selected

第二个,作为浮点数,看起来它可以转换为x86或x86-64:

我如何解释这个x86_64汇编操作码?

您看到的未初始化变量的值是该内存位置中发生的任何值。这不是随机的;它是一个由之前的函数调用存储在内存中的值。例如:

void f() {
    int i = 3;
}
void g() {
    int i;
    std::cout << i << std::endl;
}
int main() {
    f();
    g();
    return 0;
}

很有可能,这个程序(假设编译器没有优化f()中的初始化)将把3写入控制台。

浮点数是以2为基数的数制。因此,有一些特定的值不能准确地保存,并计算为近似值。

您的输出可能会给您一个特定的得到相同估计的值。尝试运行从串行连接获得的一些常见值,看看是否能找到导致您悲伤的值。我个人会用双精度数来代替浮点数,特别是当你要对这些数字做任何计算的时候。