2012-07-21 140 views
0

认真.. 我从上世纪80年代,并与一些业余时间 我的手想我应该“C”大惊小怪是关于什么的我想这个崩溃,但它并不

老黑客

(我的背景是第四,它做的事情后到前 让我学到了很多关于迫使许多错误的)

在这种情况下,我已经设置了一小阵,我 想到会是在3个要素大小(0,1,2)

如果我运行汇编,我会想到 我已经得到了一个彻头彻尾的越界错误,但NO- 它编译OK娇声

运行在这一个不很匆忙,但它 不小秃斑好,所有的scratchin' 。


int main() 
{ 
    char members[3][16]; // 3 elements, each 15 char long plus null 

    printf("\n enter something.. "); 
    scanf("%s", members[4]); 

    printf("\n and something else.. "); 
    scanf("%s", members[5]); 

    printf(" %s ", members[4]); 
    printf(" %s\n", members[5]); 

    return 0; 
} 
+1

你写一个有错误的程序,然后认为它会按照你的期望去做是不合理的。修复错误和代码将做你的期望。 Buggy代码很难理解和预测正确的代码。 – 2012-07-21 09:58:11

+1

我听到你说的话并同意。但偶尔有一次,我有代码的作品,强迫一个错误,确保我明白为什么我们不要我们不。想想这样:不知道的人不知道他们没有意识到。但是我不去极限。就像在我未来的情况下检查我的信箱,我发现空间/时间扭曲门户,并发送自己的指令来建立它 – aremvee 2012-07-21 10:09:05

+5

虽然这并不奏效。你可以在街上行走而不会看到两条路,也不会碰到汽车,并且认为它是安全的。那将是一个可怕的错误。你没有朝两边看过去,也没有被汽车撞到。绝对没有理由让你感到惊讶,当然这并不意味着它是安全的。这不是头痛的人 - 你很幸运。 – 2012-07-21 10:11:43

回答

3

C不做任何边界检查。 (Forth也没有,所以我不确定期望是从哪里来的。)

溢出数组是未定义的行为:允许但不是必需的崩溃。在这种情况下,字节恰好与放置局部变量的堆栈帧位于同一虚拟内存页面中。如果框架朝向页面的末尾,CPU将识别出错误的地址并抱怨溢出。

如果你去几千字节或几兆字节,你可能会看到像你期望的东西。

+0

我会尝试它... – aremvee 2012-07-21 10:18:25

5

访问阵列外的边界调用未定义行为。这意味着任何事情都可能发生,包括没有任何明显错误的运行。

+0

这个答案令人失望,但它收到了比这里任何其他更多的upvotes。虽然你的答案在技术上是不可理解的,但如果你仔细阅读,你可以看到他问为什么以及何时离开界限可能是危险的/产生SIGSEV。这不是一个关于standardese的问题,它更多的是关于内存管理和操作系统的问题。 – akappa 2012-07-21 10:51:23

+0

@akappa:这是解释症状的最简单的答案(迄今为止)。我可以深入讨论堆栈和虚拟内存,但我认为这个问题并不能保证(以目前的形式)。 – 2012-07-21 11:05:18

+0

@akappa - 走出界限总是**危险,特别是因为它是未定义的。如果不是,它将被定义和安全! – 2012-07-21 16:24:42

0

通常,内存分配在4 kB页面中。因此在最后一个变量之后会有一些额外的空间,并且您的缓冲区溢出未被检测到。但是,如果在您的members阵列之后存在另一个变量,并且您写信给members[4],那么另一个变量会损坏。

像valgrind和dmalloc这样的工具通常用于检测缓冲区溢出。他们通过在变量周围分配特殊保护区域并检查没有人写入变量来工作。

+1

没有更多的回复需要人,你有更好的事情 – aremvee 2012-07-21 10:14:38

0

您错过了堆栈中的主要返回地址,可能会覆盖main调用方的一些不重要的数据,因此您的程序不会崩溃。此外,在某些平台上(例如powerpc),堆栈不用于函数调用,并且返回地址存储在特殊寄存器中(当需要时将其压入堆栈)。所以这个不正确的程序不会崩溃是正常的。

更新:此外,在某些系统堆栈增长(到更高的地址)。至少在ARM堆栈增长是可选的。

相关问题