5

在同行代码审查会议期间,我看到了如下一些代码:

char *s = new char[3];
*s++ = 'a';
*s++ = 'b';
*s++='\0';
delete []s; // this may or may not crash on some or any day !!

首先,我知道在标准 C++ 中,指向过去的数组大小是可以的,尽管访问它会导致未定义的行为。所以我相信最后一行*s++='\0'很好。但如果我没记错的话,C++ 标准要求delete应该提供与new返回相同的指针。

我相信这意味着返回的指针不能被篡改。我想这是因为可能会在可能使用new的返回地址之前保留一些家政信息。delete移动new'd 指针可能会使其无法访问。

它是未定义的行为还是实现定义的或未指定的?任何人都可以确认这一点吗?最好通过指向 C++ 标准中的正确位置。

在免费提供的 C++ 标准草案 (Draft_SC22-N-4411.pdf) 的草案版本中,详细信息在第 5.3.5 节中。我是从 Bjarne 的主页上得到的。

4

3 回答 3

17

来自 C++ 标准,第 5.3.5/2 节:

delete 的操作数的值应该是从前一个数组 new 表达式产生的指针值。如果不是,则行为未定义

于 2009-04-25T07:59:03.787 回答
4

是的,你必须 delete[] new 给你的原始指针;在这种情况下,这将是指向数组头部的指针,而不是尾部。这里的代码正在删除一些其他未指定的随机对象。

于 2009-04-25T07:54:12.940 回答
3

是的,回想一下这通常是如何实现的:new 真正调用 malloc,它返回一个指向 的指针(void*)(&(((int*)p)[1])),其中 p 是分配的内存的实际开始,第一个 int 是我们返回的实际内存的大小。

我们返回的指针是实际分配的内存中的一个 sizeof(int) (或任何对齐要求)。我们把我们的物体放在那里,让实际尺寸不受干扰。

然后,当该指针传递给 delete 时,delete 将它传递给 free,free 会在传递的指针之前查找一个 int ,以找到返回的大小。

传回我们得到的东西之外的东西意味着 free 认为正在传回任意数量的实际内存,它会相应地搞砸空闲列表。

同样,这是它通常的实现方式,而不是需要如何实现 new、delete、malloc 或 free。

于 2009-05-01T03:21:08.430 回答