【问题标题】:bzero static memory vs dynamic memory [closed]bzero 静态内存与动态内存 [关闭]
【发布时间】:2019-02-02 14:13:17
【问题描述】:

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

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 字节是有效的,在我打印出计算机可以在堆栈中找到的内容之后。

【问题讨论】:

  • bzero 是一个遗留例程:不知道实现是什么。试试 memset,看看你是否得到相同的结果。
  • @jenesaisquoi 这不是真的。事实上,恰恰相反。静态链接(全局、静态)初始化为零;不是自动的。
  • 通过澄清您的问题(以及阻止错误信息,其中似乎有很多),停止对您实际上未提出的问题的大量答案。您是否观察到bzero 似乎没有将基于堆栈的数组完全归零,但似乎在动态数组上正常运行,您想知道为什么?您似乎知道动态存储和自动存储之间的区别。那么,这是关于 bzero 显然没有按您预期的那样工作吗?
  • @WhozCraig:你是对的,但这仍然不符合描述。如果编译器的行为类似于抽象机器,那么这段代码最后会产生一个垃圾值,而不是“随机数”。
  • @AnT 描述是“第一个打印一些 0 然后是垃圾”。它并没有具体说明有多少个 0 和多少垃圾。

标签: c


【解决方案1】:

bzero 的工作方式无论是分配在堆栈上还是堆上都没有区别。真正的问题在于您如何打印内容:

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

在循环的第一次迭代中,i (0) 的值与 4048 进行比较。它较小,因此进入循环,但不是在 i 递增之前。然后打印ptr[i] 的值,即ptr[1]。所以你跳过打印第一个值。

跳到最后,i 是 4047,小于 4048,所以进入循环,i 在进入循环体之前再次递增。然后打印ptr[4048] 的值,但是这个值超出了数组/分配内存的末尾,因此读取它会调用未定义的行为。在这种特殊情况下,UB 表现为两种情况都打印出不同的垃圾值。

您需要修复循环以在循环体内执行增量:

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

【讨论】:

  • 或者像通常那样使用for循环。我只是希望OP没有放弃这一点。
  • 是的,你是对的,我先走了一个。谢谢 !但是错误在其他地方。我在我的代码中使用int * 而不是char *。 char 的大小与 int 不同(1 和 4)
【解决方案2】:

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

【讨论】: