我今天编写了这段代码,仅仅是出于实验,而我正试图弄清楚输出。
/*
* This code in C attempts to exploit insufficient bounds checking
* to legitimate advantage.
*
* A dynamic structure with the accessibility of an array.
* Handy for small-time code, but largely unreliable.
*/
int array[1] = {0};
int index = 0;
put(), get();
main ( )
{
put(1); put(10), put(100);
printf("%6d %5d %5d\n", get(0), get(1), get(2));
}
put ( x )
int x;
{
array[index++] = x;
}
get ( index )
int index;
{
return array[index];
}
输出:
1 3 100
答案 0 :(得分:2)
那里有一个问题,你将'array'声明为长度为1的数组,但是你要写3个值。它至少应该是'array [3]'。没有它,你正在写入未分配的内存,所以任何事情都可能发生。
它在没有修复的情况下输出'3'的原因是它输出全局'index'变量的值,这是内存中的下一个int(在你的情况下 - 正如我所说,任何事情都可能发生)。即使您使用put(10)
调用覆盖了此值,索引值也会用作赋值中的索引,然后进行后递增,这会将其设置为2 - 然后在结束时将其设置为3调用put(100)
并随后通过printf输出。
答案 1 :(得分:1)
这是未定义的行为,所以唯一真正的解释是“它在一台机器上执行某些操作,在其他机器上执行其他操作”。
此外,K& R函数语法是什么?
编辑:printf
猜错了。就语法而言,阅读K& R第二版(封面有一个红色ANSI标记),它使用现代函数语法(以及其他有用的更新)。
答案 2 :(得分:0)
为了扩展已经说过的内容,访问越界数组成员会导致未定义的行为。未定义的行为意味着字面意思anything可能发生。没有办法利用未定义的行为,除非你深入到深奥的特定平台黑客攻击。不要这样做。
如果你想要一个“动态阵列”,你必须自己照顾它。如果您的要求很简单,您只需malloc
和realloc
缓冲区即可。如果您的需求更复杂,您可能希望定义一个结构,该结构保持单独的缓冲区,大小和计数,并编写对该结构进行操作的函数。如果您只是学习,请尝试两种方式。
最后,您的函数声明语法是有效的,但是过时了。这种形式很少见,在新代码中几乎闻所未闻。将put
声明为:
int put(int x) {…}
始终将main
声明为:
int main(int argc, char **argv) {…}
argc
和argv
的名称并不重要,但类型是。如果你忘记了这些参数,恶魔就会飞出你的鼻子。