C# 未初始化的浮点变量,重新引入不确定行为

C# 未初始化的浮点变量,重新引入不确定行为,c#,c++,.net,floating-point,undefined-behavior,C#,C++,.net,Floating Point,Undefined Behavior,我不得不调试一些表现出瞬态和零星行为的代码,这些行为最终可能归因于一行初始化中的未初始化浮点,即: float a = number, b, c = other_number; 这段代码通过串行连接对设备进行快速采样,并在一定时间间隔内平均输出。每隔一段时间,数字2.7916085e+035就会被报告,但除此之外,代码工作正常,错误无法重现 因为这个数字总是2.7916085e+035,我想可能是通信处理或设备本身出现了一些问题,但这些都被排除了。我几乎准备将其归咎于外部干扰,直到我最终在调试

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

float a = number, b, c = other_number;
这段代码通过串行连接对设备进行快速采样,并在一定时间间隔内平均输出。每隔一段时间,数字2.7916085e+035就会被报告,但除此之外,代码工作正常,错误无法重现

因为这个数字总是2.7916085e+035,我想可能是通信处理或设备本身出现了一些问题,但这些都被排除了。我几乎准备将其归咎于外部干扰,直到我最终在调试器中捕获到一个错误样本

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

在.NET framework、运行时或操作系统中是否存在导致该行为的原因?这是特别麻烦的跟踪,因为未初始化的变量总是有相同的值,而它没有被设置为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
<代码>读数是我想要平均的输出列表<代码>平均值将每…重新申报一次。。。。平均值,可以在几秒钟、几分钟、几小时内发生,也可以在满足条件时进行平均。通常情况下,变量会得到0,但偶尔会得到上面的数字。

浮点数是以2为基数的数字系统。因此,有些特定值无法准确保存,且计算结果近似


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

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

void f() {
    int i = 3;
}

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

int main() {
    f();
    g();
    return 0;
}
void f(){
int i=3;
}
void g(){
int i;

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


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

64位二进制中的双精度转换为

0100011101001010111000011101100010100101100010111110100000000000

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

双版本可能相当于

Increment by 1, where r7 (EDI - extended destination index) is selected
第二个被视为浮点数,看起来可以转换为x86或x86-64:


它似乎与您的实现的某些特定内容更为相关。您可以发布一点上下文吗?如果它是堆栈变量,则可能是堆栈上以前的任何垃圾,其本身可能是“不可复制的”,这取决于您的代码所做的。@Pedrom:是的,我在问题中提到过。数字本身很可能仅限于我的程序的上下文。我想知道为什么在我的程序的不同阶段和迭代中总是相同的,这使得跟踪变得特别困难。未初始化的变量是平均的,而不是init我可以发布一些伪代码,但我不完全确定它是否会给问题添加任何东西。我以前见过这种行为,这取决于你的操作系统。有时程序会在与以前相同的内存地址中启动。特别是如果您使用的是.Net,我希望在重新启动电脑时会有所改变。我有过这样的经历:未初始化的变量在大多数时间都有一个值,偶尔会有另一个值。这种变化是由计时器中断导致的堆栈变化引起的。由于随着时间的推移,您的行为会发生变化,这可能适用于这里。问题并没有解决“不是来自输出。未初始化的变量偶尔会得到相同的大值。小姐理解这个问题,我很抱歉。对我来说,它看起来类似于我所看到的简单使用浮点vs double的问题。如果这有任何意义的话,这可能是最大浮点大小。我认为它也可能是最大浮点大小,但这并不奇怪。你在程序运行的任何时候都在初始化这些变量吗?我也相信readings.co
Increment by 1, where r7 (EDI - extended destination index) is selected