class CheckPointer {
public:
CheckPointer(int * mbeg, int * mend) :
beg(mbeg), end(mend), curr(mbeg) {}
// subscript operator
int & operator[] (const size_t pos) {
if (beg + pos < beg) {
throw out_of_range("ERR: before beg!");
}
if (beg + pos >= end)
throw out_of_range("ERR: end or past end!");
return *(const_cast<int *>(beg + pos));
}
private:
const int * beg;
const int * end;
int * curr;
};
我为类CheckPointer定义了一个下标运算符。由于@param pos的类型为size_t,我无法检查用户是否已传递正值或负值。 Howerver我尝试编写代码来进行绑定检查,它可以工作:
if (beg + pos < beg) {
throw out_of_range("ERR: before beg!");
}
我不知道它为什么会起作用......任何人都可以帮助我吗?
感谢您考虑我的问题!
了解更多信息:
环境:eclipse CDT,Ubuntu 10.04
测试代码:
int iarr[6] = {1, 2, 3, 4, 5, 6};
CheckPointer cp(iarr, iarr+6);
// subscript
cout << cp[2] << endl;
cout << cp[5] << endl;
cout << cp[-2] << endl; // error: before beg
测试code_output:
terminate called after throwing an instance of 'std::out_of_range'
what(): ERR: before beg!
3
6
答案 0 :(得分:2)
这是有效的,因为负值被转换为无符号值。您的机器架构可能使用二进制补码表示负值,因此值为-2会导致:
0xfffffffe (assuming 32-bit)
当您将其添加到beg
时,它会回绕并且beg
大于或等于2,具有从中减去2的效果。因此,尽管索引非常大,但它基本上执行了减法。如果beg
的值为1
或0
,则错误将是“过去结束”。
答案 1 :(得分:1)
正式地,如果beg + pos
位于从beg
开始的数组之外,则beg + pos
与beg
的比较具有未定义的行为(稍微简化,但足以进行此讨论)。更好地检查坏指数将是:
if (end - beg <= pos)
但这并没有回答这个问题。将小的负值转换为size_t
会产生很大的正值;将它们视为偏移会产生一个远远超过数组末尾的指针,因此检查结果是否在边界内将会发现这个问题以及仅仅超出结束的“普通”值。