0

我不得不调试一些表现出瞬态和零星行为的代码,这最终可能归因于初始化行中未初始化的浮点数,即:

float a = number, b, c = other_number;

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

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

所以,对于这个问题。有人可以假设2.7916085e+035的重要性吗?我不确定它在我的上下文之外是否有任何意义,但令我困扰的是这个数字本质上是不可重现的reproducible。也就是说,我无法可靠地复制问题,但是当它出现时,它总是一样的。据我了解,未初始化的变量应该是不确定的。值得注意的是,问题发生在程序执行、阶段、一天中的时间等的所有不同位置……但总是在同一个系统上。

.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;
            }
         }
    }
}

这里有问题的变量是average. readings是我想要平均的输出列表。average将被重新声明一次……平均,这可以在几秒、几分钟、几小时内发生,或者在满足条件时取平均值。变量通常会得到 0,但偶尔会得到上面的数字。

4

4 回答 4

1

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 汇编操作码?

于 2013-11-03T02:50:35.367 回答
1

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

我希望从这个值本身可以推断出很少的信息。

于 2013-06-06T19:26:38.443 回答
0

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

void f() {
    int i = 3;
}

void g() {
    int i;
    std::cout << i << std::endl;
}

int main() {
    f();
    g();
    return 0;
}

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

于 2013-06-06T18:57:45.080 回答
-1

浮点数是一个以 2 为底的数字系统。因此,存在无法准确保存的特定值,并评估为近似值。

您的输出可能会为您提供一个专门获得相同估计的值。尝试运行从串行连接中获得的一些常见值,看看是否能找到导致你悲伤的值。我个人会使用双精度来代替浮点数,特别是如果您要对这些数字进行任何类型的计算。

于 2013-06-06T18:20:54.450 回答