为了避免溢出,对象可以接近最大指针值
How near to the maximum pointer value can an object be to avoid overflow?
一个有效指针(作为全局指针,在堆栈上分配,malloc
、new
、VirtualAlloc
或程序/库可能使用的任何其他分配方法)可以接近最大值多少,这样ptr + n
就有溢出的风险?
我遇到了很多在处理字符串/数组时向指针添加值的代码(在C++中,有时也在通用的"随机访问迭代器"模板函数中)。
例如
auto end = arr_ptr + len; //or just whatever some_container.end() returns
for (auto i = begin; i < end; ++i) { ... }
for (auto i = begin; i + 2 <= end; i += 2) { ...i[0]...i[1]... }
if (arr_ptr + 4 <= end && memcmp(arr_ptr, "test", 4) == 0) { ... }
if (arr_ptr + count > end) resize(...);
最后一个数组元素以0xFFFFFFFF结束(假设为32位),这样end == 0
是否有效?如果不是,它能有多近?
我认为总是使用p != end
(并且只添加1)或将长度取为len = end - begin
,然后使用它(例如(end - begin) >= 4
)总是安全的,但我想知道这是否真的是一个需要注意的问题,以及审计和更改现有代码的问题。
该标准不讨论指针溢出,而是讨论指针算术可以合法地形成哪些指针值。简单地说,合法范围是指向对象/数组的指针加上一个超过结束指针的指针。
然后,C或C++实现有责任不在某些特定于实现的危险(如指针溢出)阻止这些合法指针值正常工作的位置创建任何对象。
因此,无论是malloc
等,还是堆栈(假设您没有超过任何堆栈边界),都不会给您一个char
数组,从您无法(由于溢出)添加数组大小的地址开始。
它能有多近?
尽可能接近允许所有必需的指针值正常工作。因此,在这个32位系统上,从0xFFFFFFFE
开始的1字节对象将是最大可能的地址。标准不允许将2
添加到地址中,因此就实现而言,这样做会溢出"无关紧要"。对于一个2字节的对象,如果类型未对齐,则最大值为0xFFFFFFFD
,但这是一个奇数,因此如果需要2对齐,则为0xFFFFFFFC
。
当然,其他实现细节可能会规定一个下限。例如,系统在0的任一侧保留一页内存并使其不可访问,这并不罕见。这有助于捕捉有人访问了偏移量较小的空指针的错误。诚然,正偏移比负偏移更有可能发生这种情况,但仍然如此。如果您的32位系统决定这样做,那么malloc
将需要考虑到这一点,并且永远不会返回0xFFFFFFFE
。
- 1d 智能指针不适用于语法 (*)++
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 为什么使用 "this" 指针调用派生成员函数?
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用指针从C++中的数组中获取最大值
- 助记符和指向成员语法的指针
- 嵌入方指针压缩已禁用
- 数组的指针从不分段故障
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 何时在引用或唯一指针上使用移动语义
- QMetaObject invokeMethod的基于函数指针的语法
- 如何从 std::atomic 中提取指针 T<T>?
- 如何在 C# 中映射双 C 结构指针?
- C++将浮点指针值舍入为小数位数
- 为什么++(*p)更改指针值
- 调整大小后指向元素值的指针unordered_map有效?
- 正在将指针转换为范围
- 使用指向成员的指针将成员函数作为参数传递
- 为什么未初始化的指针会导致接近 0 的 mem 访问冲突
- 为了避免溢出,对象可以接近最大指针值