清零静态内存 VS 动态内存

3

我的问题是:这两行代码有什么区别:

int ptr[4046];
bzero(ptr, 4046);

int *ptr;
ptr = (int *)malloc(sizeof(int) * 4046);
bzero(ptr, 4046);

我提出这个问题是因为当我想输出ptr时,第一个打印一些0然后是垃圾(随机数字),而第二个(使用malloc)只打印0,就像我希望的那样。我使用printf来输出,如下:

int i = 0;
while (i++ < 4046)
  printf("%x", ptr[i]);

编辑: 感谢大家的回答, 答案是:int类型的大小不是1个字节,而是4个字节。因此前4046个字节是有效的,之后我打印计算机在堆栈中找到的内容。


3
@jenesaisquoi说的不是真的。事实上正好相反。静态链接(全局变量、静态变量)会被初始化为零;自动变量不会。 - WhozCraig
1
通过澄清问题(以及遏制误导,其中似乎有很多),停止即将到来的对你实际上没有提出的问题的回答洪水。您是否观察到 bzero 似乎无法完全将基于堆栈的数组置零,但在动态数组上似乎可以正常工作,并且您想知道原因?您似乎知道动态和自动存储之间的区别。那么,这是关于 bzero 显然不按您的预期工作吗? - WhozCraig
@WhozCraig:你说得对,但这仍然不符合描述。如果编译器的行为像抽象机器一样,这段代码最终只会产生一个垃圾值,而不是“随机数”。 - AnT stands with Russia
@AnT 描述为“第一个打印一些0,然后是垃圾”。它没有明确说明有多少个0和多少垃圾。 - dbush
使用4048是一个不寻常的数字。2048或4096都非常普通。 - Jonathan Leffler
显示剩余3条评论
2个回答

4

bzero 的工作原理无论内存是在堆栈上还是在堆上都没有区别。真正的问题在于你打印内容的方式:

int i = 0;
while (i++ < 4048)
  printf("%x", ptr[i]);

在循环的第一次迭代中,将i(0)的值与4048进行比较。它小于4048,因此进入循环,但在进入循环之前会先将i增加。然后打印ptr[i]的值,即ptr[1]。因此跳过了第一个值的打印。
跳到最后,i为4047,小于4048,因此进入循环,再次在进入循环主体之前对i进行增量操作。然后打印ptr[4048]的值,然而这个值已经超过了数组/分配内存的末尾,因此读取它会导致未定义行为。在这种情况下,UB表现为每个情况都打印不同的垃圾值。
您需要修复循环以在循环主体内执行增量操作。
int i = 0;
while (i < 4048)
  printf("%x", ptr[i++]);

1
或者像通常做的那样使用for循环。我只希望原帖作者没有放弃这个问题。 - WhozCraig
是的,你说得对,我错了一位。谢谢!但错误在别处。我的代码中使用了 int * 而不是 char *。char 的大小与 int 不同(分别为 1 和 4)。 - MaxenceJdeD

0

第一个在栈上分配内存,第二个在堆上分配内存


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接