什么可能导致变量改变价值?

时间:2014-03-27 01:11:27

标签: c++ variables memory-management

我接受了一位科技巨头的电话采访,其中一个问题是这样的:

假设您有一个功能并且在您拥有的功能中

int i = 100;

你在功能中做了一些其他的事情,而没有触摸变量i,稍后你打印我,你看到的值是不同的。什么可能导致变化?

我回答:某种内存损坏,内存溢出......等等。他们似乎并不满意答案。现在我想到堆栈指针搞砸了。有什么我想念的吗?

6 个答案:

答案 0 :(得分:2)

在if语句中错误地使用单个等号(赋值)而不是双等号(比较)是一种好方法。

答案 1 :(得分:2)

您在不同的范围使用其他本地i变量名称(例如,在for循环,更深的范围,全局声明,模块/函数静态,成员变量,...),等等i您认为您正在打印出来的不是您实际打印的i

另一种可能性 - 参考。另一个引用i的变量。

答案 2 :(得分:1)

  

int i = 100

如果您在函数内定义它,它将在STACK变量上。因此,如果以任何方式(.i.e。通过传递具有溢出的参数或函数内的其他局部变量溢出),它可以更改“i”的值。这可能是由于堆栈溢出/损坏而发生的。

但是这样的场景可能导致函数的堆栈指针/返回值损坏,这最终会导致程序崩溃/未定义。

答案 3 :(得分:1)

当函数返回时,i的那个版本完全消失,因为它是在函数内声明的局部变量,所以它的生命周期与函数有关。在函数外部打印出来的i版本(之后)是完全不同的i,在函数之前定义

答案 4 :(得分:1)

这种类型的东西(假设你指的是同一个i,这意味着你打印i的值在同一个函数中)。

#include <stdio.h>

void f()
{
    char buf[100];
    int i = 100;
    int j;

    for (j = 0; i <= 100; j++){
       buf[j] = 255;
    }

    printf("i=%d\n", i);
}

int main(int argc, char* argv[])
{
    f();
    return 0;
}

猜猜是什么印刷的?是的。 I = 255。我试图在这里展示的是,我们可以超出缓冲区并填充后面变量的内容。

更为微妙的做法是滥用sizeof。

e.g。

  int array[100]
  sizeof array  != 100

  So you can't do
  for (i = 0; i < sizeof array; i++)  // very bad!

因此,您可以看到错误如何导致缓冲区溢出。

但是,对于现代版本的gcc,上面的代码将进行核心转储。包括第一个。我必须使用-fno-stack-protector选项实际编译它,以使其在不转储核心的情况下打印结果。如果你做了一个尺寸,它会立即转移核心。

答案 5 :(得分:1)

  

我回答:某种内存损坏,内存溢出等等。

非常合理的开始。

&#34;没有触及变量i&#34;有点模糊,因为显而易见的i被触动了,所以我们不得不猜测什么样的触摸不够明显,不能算作触摸。也许:

未定义的行为 :所有投注都已关闭....

引用和指针 :如果创建了非const引用或指向i的指针,则可能i间接修改。它也可能是指向该堆栈地址的悬空指针(但不是&#34;您的&#34; i)被赋予某些异步中断或其他线程,并且您的i可以通过其使用来修改。

中断处理 :通常不关心应用程序代码,但如果您编写自己的中断处理程序 - 或尝试某些alpha / beta代码 - 它们可能会意外地搞乱您的堆栈,甚至破坏编译器期望i可用的寄存器

内联汇编语言 :如果编译器将i加载到寄存器中,并且您在某些内联汇编中对寄存器执行了某些操作编译器没有推送/保存和弹出/恢复值,i在打印时似乎已经改变了

off-by-one error 可能导致此问题:

char s[3];
int i = 100;
... do something that loads text into c that might not be terminated ...
s[sizeof s] = '\0'; // "ensure termination" / actually off by one

不可否认,这有点超出&#34;溢出&#34;虽然它不是&#34;很酷&#34;善待fscanf("%s", &s);,可以任意远远超过s

其他想法:

  • 线程可能具有相关性,因为不受审查的语句可能会与i混淆,但每个线程都有一个单独的堆栈,因此它会采取严重的损坏/未定义的行为

  • &#34;稍后你打印我&#34; - 我认为它不是他们正在寻找的东西,但是有一种方法可以填补这个问题:用十六进制打印和思考值64与预期的100小数不同,从另一个范围打印i,&#34;干扰&#34;来自其他印刷语句(可能在其他线程中),例如打印&#34; 0&#34;使i似乎是&#34; 1000&#34;