执行operator new的任何实现都返回指向大小为零的数组的保护页的指针
Do any implementations of operator new return a pointer to a guard page for zero-size arrays?
相关:c++ new int[0]——它会分配内存吗?
标准在5.3.4/7中说:
当direct-new-declarator中表达式的值为0时,调用分配函数分配一个没有元素的数组。
…并且,在3.7.3.1/2:
请求大小为0的指针解引用的效果是未定义的。
…但是,该指针不能为空指针。
由于实际解引用指针是未定义的行为,是否有任何实现返回指针到保护页?我想这会很容易,并且有助于检测错误/提高安全性。
我看了(草案)标准,我找不到任何明确禁止这一点的东西。不过,我猜答案是"不"。原因如下:
- 正如你所说,new需要返回一个非空指针。
- 此外,无论返回什么,传递给delete都必须是安全的。
- 所以"随机值"不起作用,因为它会破坏删除。
- 还要求每次调用返回不同的值(至少在它们被删除之前)-参见c++标准部分basic.stc.dynamic.allocation。在这一点上只有一个选择:返回"假指针",以某种方式被delete识别为"假指针"。
一种可能的实现可以通过保留一个未分页内存范围来实现,并且每次有人调用new int[0]时,它可以返回该范围内的不同地址(如果分配器保留全局计数器或类似的东西,则很容易做到)。
有利的一面是,您将获得立即检测这种类型指针上的解引用的能力。另一方面,您将失去检测双自由度的能力,因为指针上的delete操作实际上变成了no操作,并且对于所有正常情况,您将使new和delete操作更加复杂和缓慢。
因为这很棘手,而且弊大于利,所以我很有信心没有人会这样做。
Linux上的gcc只分配少量内存并返回。我相信这是一种很标准的方式
为了跟踪需要释放多少内存,我查看或编写的大多数分配器如下所示:
void *malloc_example(size_t bytes) {Size_t *ret = get_memory(bytes + sizeof Size_t);/*查找空闲内存*/*ret = bytes;/*记住分配区域的大小*/Return (void *)(ret + 1);} 之前所以当你分配零长度块时,你实际上会在返回给你的地址之前得到一个隐藏的单词。这也确保了每个分配都被分配一个唯一的地址。这是很重要的,指向零长度块的专用保护内存更像是浪费,因为每个free都必须测试我的经验所说的罕见情况。
一些调试分配器包括捕获双自由度、内存泄漏、捕获先前缓冲区溢出的保护字等额外开销。此外,指向一些神奇的内存可能会使此类调试更加困难。
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 为char数组调整zlib-zpipe
- 在索引0为0的数组中查找非零最小值C++
- 使用数组将最后一个最大值更改为第一个最小值
- 以 C/C++ 为单位的数组中最小值的地址
- 构造大小为 N 的数组 A 和大小为 1 的数组 A,使得所有 A[i]*A[j] 的总和为最小值和正数。1 <= i < j <= N
- 将动态分配的数组的大小调整为较小的大小C++
- 最小的正乘数,当应用于数组时,使数组成为积分
- 如何从大到小组织数组中的前 10 个常用值
- C++将大型数组拆分/分区为较小的数组
- 我应该如何将较小的std::数组构造为较大数组的切片
- 如何计算将数组中的所有n个数转换为m的最小成本
- 将一个std::数组拆分为一个较小大小的std::array元组
- 在最小执行时间内找到给定数组中和为零的所有唯一三元组
- 用较小的数组初始化C++std::数组
- 查找最小字典数组
- 将数组大小调整为较小的大小,保留相同的名称,删除数组中旧的位置
- 为什么std::equal比两个小std::数组的手卷循环慢得多?
- 在一个非常小的数组中找到最小值
- 是否有STL函数将c风格的数组拆分/拼接成更小的数组?