【问题标题】:How are the values of uninitialized variables determined?未初始化变量的值是如何确定的?
【发布时间】:2012-10-12 16:57:25
【问题描述】:

给定一个程序:

int main()
{

    short myVariableName1;  // stores from -32768 to +32767
    short int myVariableName2;  // stores from -32768 to +32767
    signed short myVariableName3;  // stores from -32768 to +32767
    signed short int myVariableName4;  // stores from -32768 to +32767
    unsigned short myVariableName5;  // stores from 0 to +65535
    unsigned short int myVariableName6;  // stores from 0 to +65535

    int myVariableName7;  // stores from -32768 to +32767
    signed int myVariableName8;  // stores from -32768 to +32767
    unsigned int myVariableName9;  // stores from 0 to +65535

    long     myVariableName10;  // stores from -2147483648 to +2147483647
    long     int myVariableName11;  // stores from -2147483648 to +2147483647
    signed   long myVariableName12;  // stores from -2147483648 to +2147483647
    signed   long int myVariableName13;  // stores from -2147483648 to +2147483647
    unsigned long myVariableName14;  // stores from 0 to +4294967295
    unsigned long int myVariableName15;  // stores from 0 to +4294967295
    cout << "Hello World!" << endl;
    cout << myVariableName1 << endl;
    cout << myVariableName2 << endl;
    cout << myVariableName3 << endl;
    cout << myVariableName4 << endl;
    cout << myVariableName5 << endl;
    cout << myVariableName6 << endl;
    cout << myVariableName7 << endl;
    cout << myVariableName8 << endl;
    cout << myVariableName9 << endl;
    cout << myVariableName10 << endl;
    cout << myVariableName11 << endl;
    cout << myVariableName12 << endl;
    cout << myVariableName13 << endl;
    cout << myVariableName14 << endl;
    cout << myVariableName15 << endl;
    cin.get();

    return 0;
}

打印出未分配的变量将打印之前存储在该内存位置的任何内容。我注意到的是,在多次连续执行中,打印的值没有改变——这告诉我每次执行时内存中的位置都是相同的。

我只是好奇这是如何确定的,为什么会这样。

【问题讨论】:

  • 你是在调试还是发布模式?
  • "我只是好奇这是如何确定的" - 值是不确定的。这意味着他们没有下定决心。

标签: c++ initialization


【解决方案1】:

这些变量存在于堆栈中。程序的执行看起来是确定性的,所以每次运行时都会发生相同的事情。它不一定要选择相同的地址(现在许多运行时都使用地址空间随机化技术来确保堆栈地址在运行之间相同),但堆栈上的相对地址包含相同每次都有数据。

【讨论】:

  • 首先谢谢你。其次随机位置怎么可能包含相同的数据?
  • 你似乎还是一头雾水。内存在被映射之前被擦除为零,当进程开始运行时,内存中没有“现有内容”。您会在这些字节中看到非零数据,因为 您的程序(虽然不是您的代码本身)将它们放在那里。而且每次都是一样的,因为你的程序每次都做同样的事情。
  • 如果我附加了一个程序集调试器,那么我应该能够看到那些设置为这些值的内存位置?
  • 是的,但这会很困难。动态链接的 linux 程序实际上在 ld.so 中开始执行,并在调用 _start(调用 main)之前运行大量代码。你需要做一些关于在那里设置断点的研究,我不知道怎么做。
【解决方案2】:

它们可以是任何东西不要依赖它们来成为任何特定的东西。
从技术上讲,这些值是不确定

请注意,使用 Indeterminate 值会导致未定义行为

【讨论】:

  • 这比帮助更令人困惑。您对“不确定”和“未定义”的使用是指 C 语言规范。海报有一台真实的机器,真实的值存储在真实的内存中。问题是为什么这些值在运行之间是相同的。说它们是“未定义的”而不参考你的意思(显然内存内容是真实的并且定义得很好!)并不能回答这个问题。
  • @AndyRoss:真实机器,真实值存储在真实内存中不会以任何可能的方式使行为具有确定性。根据标准,行为是未定义的,并且这是唯一正确的解释。
  • 一台真实机器的行为不是确定性的吗?我认为您对计算机的工作方式感到困惑,我敢肯定您对我的批评感到困惑。可以根据语言标准来争论设计点。但这不是问题所在。
【解决方案3】:

它们都是基于堆栈的。可能启动代码已经使用了这些位置,所以你会得到它留在其中的任何东西。

【讨论】:

  • +1 尤其是当使用cout 时,正在进行一些初始化以构建所有这些静态对象。
  • 谢谢!那么根据该理论,只要 sizeof 相同,改变它们的初始化顺序就应该产生相同的结果?
【解决方案4】:

该行为未定义为“之前存储在该内存位置中的任何内容”,而是根本没有定义。无法保证会发生什么

我的最佳猜测是您的操作系统正在使用虚拟内存(就像大多数现代操作系统一样),因此每次都为您提供相同的内存地址。

【讨论】:

  • 内存中的地址相同的事实并不能解释为什么该地址处的内容会相同。
  • 虚拟内存位与内存映射地址选择无关。事实上,映射在运行时被半随机化越来越普遍。但无论如何地址都不是问题 - OP 看到的症状是内存的 contents 在运行之间是相同的,而不是地址。在现代操作系统中,内存内容从不从一个进程保留到另一个进程。
【解决方案5】:

与人类不同,计算机是确定性的。

在读取尚未赋值的变量时,通常使用编译器选项来获取是个好主意。

所以操作系统每次都会提取代码并执行完全相同的操作。因此结果相同。

但是,如果您开始摆弄代码,可执行文件会有所不同。由于您没有具体说明,因此下次您会得到不同的结果。

因此,总而言之,只需使用编译器的所有功能来帮助您发现此错误,并养成在使用该变量之前给变量值的习惯。

【讨论】:

  • 我实际上是故意这样做的,执行几次后发现值没有改变。因此,我很好奇内存地址是如何分配给变量的。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-23
  • 1970-01-01
相关资源
最近更新 更多