有效指针有多接近最大值(作为全局,在堆栈上分配,malloc
,new
,VirtualAlloc
或任何其他alloc方法/程序/库可能会使用),这样ptr + n
冒着溢出的风险?
我遇到了很多代码,在处理字符串/数组时会为指针添加值(在C ++中,有时也在通用的“随机访问迭代器”模板函数中)。
e.g。
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
)总是安全的,但想知道它是否真的要注意的问题,并审核和更改现有代码。
答案 0 :(得分:3)
标准没有讨论指针溢出,它讨论了指针运算可以合法地形成什么指针值。简单地说,合法的范围是指向你的对象/数组的指针加上一个过去的指针。
然后,C或C ++实现的责任是不在某些特定于实现的危险(如指针溢出)阻止那些合法指针值正常工作的位置创建任何对象。
因此,malloc
等,也不是堆栈(假设你没有超过任何堆栈边界)将给你一个char
数组,从你不能到达的地址开始(到期)溢出)添加数组的大小。
它有多接近?
尽可能允许所有必需的指针值正常工作。因此,在这个32位系统上,从0xFFFFFFFE
开始的1字节对象将是最大可能地址。该标准不允许您将2
添加到地址,因此它并不重要&#34;就实施而言,这样做会溢出。对于一个2字节的对象,如果类型是未对齐的,则最大值为0xFFFFFFFD
,但这是一个奇数,所以0xFFFFFFFC
如果它需要2对齐。
当然,其他实施细节可能会规定下限。例如,系统在0的任一侧保留一页内存并使其无法访问并不罕见。这有助于捕获有人访问具有小偏移量的空指针的错误。当然,这更可能发生在正偏移而非负面,但仍然如此。如果您的32位系统决定这样做,那么malloc
需要考虑它,并且永远不会返回0xFFFFFFFE
。