C++ 为了避免溢出,对象离最大指针值有多近?

C++ 为了避免溢出,对象离最大指针值有多近?,c++,pointers,C++,Pointers,有效指针(作为全局指针,在堆栈上分配,malloc,new,VirtualAlloc,或程序/库可能使用的任何其他alloc方法)与最大值的接近程度,使得ptr+n风险溢出 我遇到了很多代码,这些代码在处理字符串/数组时增加了指针的值(C++中有时也在一个通用的“随机访问迭代器”模板函数中)。 e、 g auto end=arr\u ptr+len//或者只是一些容器返回的内容 对于(自动i=begin;i

有效指针(作为全局指针,在堆栈上分配,
malloc
new
VirtualAlloc
,或程序/库可能使用的任何其他alloc方法)与最大值的接近程度,使得
ptr+n
风险溢出

我遇到了很多代码,这些代码在处理字符串/数组时增加了指针的值(C++中有时也在一个通用的“随机访问迭代器”模板函数中)。 e、 g

auto end=arr\u ptr+len//或者只是一些容器返回的内容
对于(自动i=begin;ifor(auto i=begin;i+2=4)总是安全的,但是想知道它是否真的是一个需要注意的问题,是否需要审核和更改现有代码。

该标准没有讨论指针溢出,而是讨论指针算术可以合法地形成什么指针值。简单地说,合法范围是指向对象/数组的指针加上一个超过结束指针的指针

然后,C或C++实现的责任不是在某些特定的危险如指针溢出的位置创建任何对象,防止这些合法的指针值正确工作。 因此,无论是

malloc
etc,还是堆栈(假定您没有超过任何堆栈边界)都不会给您一个
char
数组,从您无法(由于溢出)添加数组大小的地址开始

有多近

尽可能接近允许所有必需的指针值正常工作。因此,在这个32位系统上,从
0xFFFFFFFE
开始的1字节对象将是可能的最大地址。该标准不允许您向地址添加
2
,因此,就实现而言,这样做会溢出“无关紧要”。对于2字节对象,如果类型未对齐,则最大值将为
0xfffffd
,但这是一个奇数,因此如果需要2对齐,则最大值将为
0xfffffc


当然,其他实现细节可能会规定一个下限。例如,系统在0的任一侧保留一页内存并使其不可访问,这并不罕见。这有助于捕获有人访问带有小偏移量的空指针时的错误。诚然,正偏移量比负偏移量更可能发生这种情况,但仍然如此。如果您的32位系统决定这样做,那么
malloc
将需要考虑它,并且永远不会返回
0xFFFFFFFE

标准并没有讨论指针溢出,而是讨论指针算术可以合法地形成什么指针值。简单地说,合法范围是指向对象/数组的指针加上一个超过结束指针的指针

然后,C或C++实现的责任不是在某些特定的危险如指针溢出的位置创建任何对象,防止这些合法的指针值正确工作。 因此,无论是

malloc
etc,还是堆栈(假定您没有超过任何堆栈边界)都不会给您一个
char
数组,从您无法(由于溢出)添加数组大小的地址开始

有多近

尽可能接近允许所有必需的指针值正常工作。因此,在这个32位系统上,从
0xFFFFFFFE
开始的1字节对象将是可能的最大地址。该标准不允许您向地址添加
2
,因此,就实现而言,这样做会溢出“无关紧要”。对于2字节对象,如果类型未对齐,则最大值将为
0xfffffd
,但这是一个奇数,因此如果需要2对齐,则最大值将为
0xfffffc


当然,其他实现细节可能会规定一个下限。例如,系统在0的任一侧保留一页内存并使其不可访问,这并不罕见。这有助于捕获有人访问带有小偏移量的空指针时的错误。诚然,正偏移量比负偏移量更可能发生这种情况,但仍然如此。如果您的32位系统决定这样做,那么
malloc
将需要考虑它,并且永远不会返回
0xFFFFFFFE

,我非常确定语言标准没有定义这一点(C和C++),它取决于底层硬件体系结构(内存管理单元、虚拟内存大小、分页等)。我很确定语言标准没有定义这一点(C和C++),它取决于底层硬件体系结构(内存管理单元、虚拟内存大小、分页等)。因此,实际上,任何“malloc(n)”函数都要求“malloc(n)=4”是正确的,但是“开始+4左右。但是,从地址的数字值的角度考虑几乎没有任何好处。实际上并不能保证
uintptr\t
存在,或者溢出是可以形成指针的唯一限制。添加超过数组大小的内容会有未定义的行为,因此是一个潜在的错误,无论其根本原因是算术溢出还是程序员从未听说过的一些不同的实现细节。我只使用UINTPTR_MAX,因为“VOID_PTR_MAX”没有。“(t*)Maloc(siZOF(t))+ 1对于任何‘分配方法’总是定义的,并且不能溢出“可能是更好的TeleMe”@ Firace:是的,你已经得到了:-我懒得查不到确切的引用,但是IIRC都是在C和C++标准的“操作符”部分中添加的,所以实际上,任何“Malc(n)”都是定义的。函数要求“malloc(n)=4”是正确的,但“begin+4”或多或少是正确的。但是,考虑地址的数值几乎没有任何好处。实际上不能保证
uintptru\t
存在
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(...);