Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是否有任何运算符new的实现返回指向零大小数组的保护页的指针?_C++_New Operator - Fatal编程技术网

C++ 是否有任何运算符new的实现返回指向零大小数组的保护页的指针?

C++ 是否有任何运算符new的实现返回指向零大小数组的保护页的指针?,c++,new-operator,C++,New Operator,有关: 标准在5.3.4/7中规定: 当直接新声明符中表达式的值为零时,将调用分配函数来分配不含元素的数组 …在3.7.3.1/2中: 取消引用作为零大小请求返回的指针的效果未定义 …但是,指针不能是空指针 由于实际取消引用指针是未定义的行为,任何实现是否会返回指向保护页的指针?我想这很简单,可以帮助检测bug/提高安全性。我查看了(草案)标准,但没有发现任何明确禁止此操作的内容。不过,我猜答案是“不”。这就是为什么: 正如您所说,返回非空指针需要new 此外,无论返回什么,都必须安全地传递给

有关:

标准在5.3.4/7中规定:

当直接新声明符中表达式的值为零时,将调用分配函数来分配不含元素的数组

…在3.7.3.1/2中:

取消引用作为零大小请求返回的指针的效果未定义

…但是,指针不能是空指针

由于实际取消引用指针是未定义的行为,任何实现是否会返回指向保护页的指针?我想这很简单,可以帮助检测bug/提高安全性。

我查看了(草案)标准,但没有发现任何明确禁止此操作的内容。不过,我猜答案是“不”。这就是为什么:

  • 正如您所说,返回非空指针需要new
  • 此外,无论返回什么,都必须安全地传递给delete
  • 所以“随机值”不起作用,因为它会破坏delete
  • <> LI>还需要为每个调用返回不同的值(至少在删除之前)——参见C++标准节Basic .STC.Dealth.Dealial.< /LI>
  • 此时只剩下一个选项:返回“伪指针”,delete可以将其识别为“伪指针”
一种可能的实现方法是保留一个未分页内存范围,每次有人调用new int[0]时,它都会返回该范围内的不同地址(如果分配器保留一个全局计数器或类似的东西,那么很容易做到)

有利的一面是,您将获得立即检测此类指针上的解引用的能力。另一方面,您将失去检测双重释放的能力,因为指针上的delete实际上变成了no-op,并且对于所有正常情况,您将使new和delete更加复杂和缓慢

所以,因为这很难做到,而且利大于弊,我很有信心没有人会这么做


linux上的gcc只分配少量内存并返回该内存。我相信这几乎是一种标准方法。

要跟踪需要释放多少内存,我在其中查找或编写的大多数分配器如下所示:

void *malloc_example( size_t bytes ) { size_t *ret = get_memory(bytes + sizeof size_t); /* find free memory */ *ret = bytes; /* remember size of allocated area */ return (void *)( ret + 1 ); } void*malloc\u示例(大小\u t字节){ size_t*ret=get_内存(字节+size_t的大小);/*查找可用内存*/ *ret=bytes;/*记住分配区域的大小*/ 退货(作废*)(退货+1); } 因此,当您分配零长度块时,您实际上会在返回给您的地址之前得到一个鬼鬼祟祟的单词。这也确保每个分配都分配了一个唯一的地址。这很重要,指向零长度块的专用保护内存更是一种浪费,因为根据我的经验,每个空闲块都必须进行测试,这是一种罕见的情况


一些调试分配器包括额外的开销以捕获双重释放、内存泄漏、保护字以捕获以前缓冲区的溢出等。此外,指向一些神奇的内存可能会使此类调试更加困难。

唯一性问题可能(可能)导致重复使用同一页,这意味着每零字节分配约4k内存空间。。。或者,我们可以分配一个“未使用的”页面,然后分配一组页面,在这些页面中,我们将每个地址用于一个不同的数组,然后再分配一个空的保护页面。然而,这一切似乎都是为了一些不常使用的东西而过度工程化,不是吗?过度工程化?我们讨论的是动态内存分配的实现,它几乎被程序的每个部分使用!当然,一点额外的工程是值得的吗?除非你谈论的是复杂性/性能-是的,这是另一个要测试的代码路径,有点额外的复杂性,在一个非常热门的函数中有更多的代码。我认为@Yakk意味着零元素数组不经常使用。我倾向于同意这一点。对于
0
大小的数组,访问索引
0
处的元素与对于1大小的数组,访问索引
1
处的元素有什么根本区别?为什么我们要在第一种情况下进行特殊分配?@AlexD事实上,调试堆在页面末尾的每个分配中都包含一个受保护的页面,以捕获“一个接一个”的错误,这是一个在真正的工具链中使用的巧妙技巧(我看到了…育碧软件Montreal guy mayhap的演讲)。对于零大小数组,每次分配需要花费您一页。您是对的-我在标准中找到了相关部分(basic.stc.dynamic.allocation)并更新了答案。