这个变量的值在我的C代码中是如何变化的?

时间:2010-02-13 18:11:16

标签: c

我在C中遇到过一个我以前从未遇到的奇怪问题。我已将其缩小到以下非常简单的片段。

变量是全局的,类型为:

    int cpd;
    int nPart;

这是相关的代码片段,我逐渐将其删除到产生问题所需的最低限度:

    printf("\ncpd1: %d\n",cpd);

    int p;
    for(p=1;p<=nPart;p++)
    {
        printf("\ncpd2: %d\n",cpd); exit(0);
    }

...我得到的输出是:

cpd1: 17

cpd2: 0

这究竟是怎么可能的?! cpd还没有被重新分配,没有调用任何函数......但它改变了吗? 怎么样?!?!

这让我慢慢疯了一段时间了...... ......所以任何想法?

谢谢你的时间, 本。

编辑:当我从gcc的makefile参数中删除-02时,打印语句告诉我cpd = 0!

编辑:好的,我刚刚发现一个全局声明的变量,初始化为4.0,然后从未被修改过,现在显然是1.51086e-311 ......某处出了点问题......

编辑:已解决!:我有一个大小为1000的数组需要超过4000,并试图写这个是破坏它周围的记忆。事实是,这些数组不会在那些打印语句附近的任何地方被访问, 在同一个函数中被访问,但更早的时候(大函数!)。打印语句之间的奇怪差异必须是使用-O2的一些奇怪的假象,因为没有-O2,两个打印的cpd打印损坏的版本。谢谢大家,没有你的帮助我不会这样做!

7 个答案:

答案 0 :(得分:15)

由于缓冲区溢出导致的堆栈帧损坏通常是对此的解释。这是一个例子:

#include <stdio.h>
#include <string.h>

int main()
{
  int cpd;
  char msg[4];
  cpd = 17;
  printf("%d\n", cpd);
  strcpy(msg, "Oops");
  printf("%d\n", cpd);
  return 0;
}

输出:

17
0

“msg”字符串缓冲区太短一个字符,字符串终止符会覆盖“cpd”的值。

找到原因的最佳方法是使用调试器的数据断点功能。在函数入口点上设置常规断点。然后找到“cpd”变量的地址,并在其上设置一个字节大小的数据断点。一旦cpd值改变,调试器就会停止。

请注意,这不一定适用于优化代码,“cpd”值可能存储在寄存器中。这是另一种可能的解释,为什么它在不同的陈述中的价值不同。

答案 1 :(得分:5)

我能想到的唯一可能的原因是你声明了另一个本地int cpd变量。 作为一个例子,我拿了你的代码并稍加修改它以添加另一个int cpd声明并将其保留为未初始化:
注意我必须设置nPart = 1,因此for循环至少执行一次

#include <stdio.h>

int cpd;
int nPart = 1;

int main (int argc, char ** argv)
{
 printf("\ncpd1: %d\n",cpd);
 int cpd;


    int p;

    for(p=1;p<=nPart;p++)
    {
        printf("\ncpd2: %d\n",cpd); 
  break;
 }
}

当我跑步时,我得到以下输出:
cpd1:0

cpd2:2130567168

正如预期的那样,全局变量cpd为0,本地cpd未初始化,几乎可以是任何32位值。

答案 2 :(得分:3)

张贴的内容无法做到。唯一的解释是,其他东西正在改变cpd,或者cpd有多个实例。

答案 3 :(得分:3)

int main() {
    int cpd = 13;
    int nPart = 17;

    printf("\ncpd1: %d\n",cpd);

    int p;

    for(p=1;p<=nPart;p++) {
            printf("\ncpd2: %d\n",cpd);
    }

    exit(0);
}

这为我编译并运行预期的输出。我是否错误地复制了您的示例,或者在for循环结束时是否缺少右括号(并且包含后续的exit(0)有目的的?

编辑:假设适当的包含。

答案 4 :(得分:2)

您需要发布一个完整,最小化,可编辑的程序。例如,以下程序:

#include <stdio.h>
#include <stdlib.h>

int cpd = 17;
int nPart = 10;

int main(void)
{
    int p;

    printf("\ncpd1: %d\n",cpd);

    for(p=1;p<=nPart;p++)
    {
        printf("\ncpd2: %d\n",cpd); exit(0);
    }
    return 0;
}

打印17次。

注意:

  • nPart初始化为&gt; = 1,否则循环甚至不执行一次。
  • 我分别为stdio.hstdlib.h添加了printf()exit()
  • 我将exit(0);调用留在循环中 - 不知道为什么你有它在那里,因为这意味着循环最多只执行一次。

答案 5 :(得分:0)

未初始化的变量可以具有任何值,通常在调试版本中它将被设置为零,但您不能依赖于此。

答案 6 :(得分:0)

如果您发布的最小代码段确实重现了问题,那么这里唯一的解释是您的编译器无可救药地被破坏并生成无意义的破坏代码。

但是,我强烈怀疑你发布的代码片段并不完整(显然是不可编译的),问题出在您省略的代码中。