(非)循环中的静态对象

时间:2010-09-03 17:50:21

标签: c++ static

在一本书中有一个关于静态/非静态对象的例子。

char buf[MAX];
long count=0;
int i=0;
while(i++<=MAX)
    if(buf[i]=='\0') {
        buf[i]='*';
        ++count;
    }
assert(count<=i);

据说有时代码会将buf数组的末尾写入count并使断言失败。然后讲述将计数声明为静态并解决问题(注意:作者将此作为一个不好的解决方案示例)无论如何,除了一个坏的例子,我无法弄清楚问题是如何发生的,以及如何解决它作为声明算作静态。

5 个答案:

答案 0 :(得分:4)

这不仅仅是糟糕的解决方案,而是非解决方案。您不能索引数组的边界。如果这样做,则在实现正确的C ++程序方面存在不可解决的问题。

您可能会在常见的C ++实现中看到,有时count会在buf之后直接放入堆栈。因此,如果你过度索引然后写,你可以修改count,然后任何纯粹基于直接写入它的count值的假设不再正确,因为有写通过过度索引操作来实现它。

如果您现在将变量设为static,则在程序的其他部分中分配(通常为{0}初始化的.bss和其他初始化数据的.data,常见实现上的count变量将不再分配在数组旁边,这将导致另一个事件发生:而不是覆盖count,您可能会覆盖数组旁边的任何内容。

答案 1 :(得分:3)

该示例依赖于内存中变量的特定布局,即count恰好位于buf之后。通过使count静态,它被放置在内存的不同部分,而其他东西则被破坏。问题没有消失,症状刚刚改变。

答案 2 :(得分:1)

约翰内斯的回答是正确的。

但是,为什么将count声明为static可能会使出现。当count被声明为非static时,它通常会在内存中buf[]之后立即生效(在堆栈上)。但是,当声明为static时,它不会在堆栈中,因此当您在buf[]的末尾写入时不会损坏。

答案 3 :(得分:0)

我同意,如果超过数组边界,则会导致超出范围的异常。或者在非托管语言(如C / C ++)中,你可能最终写入/读入下一批内存地址,我的非空终止字符串的内存运行到另一个对象内存中并不好玩。

我有点好奇你的静态对象在哪里,你把它们全部声明为变量,看不到静态对象。

上面的代码应该总是超过数组,因为我首先检查了max,然后增加了i,这使得我增加了一个最大值,给你一个1的错误。

答案 4 :(得分:0)

我想阅读这本书,但我想它会显示“巫毒编程”的例子,你会尝试随机的东西,直到它停止破坏,并称之为成功。

正如其他地方所提到的,通过将其声明为静态来做的所有事情都是移动计数到不同的地方,这意味着断言可能会通过。对于没有经验的程序员来说,这足以提交,此时您在生产环境中有缓冲区溢出代码。

当然,我希望“i”会被覆盖,这会更糟糕,因为它是循环的控制变量,但我可能错了。