2012-11-25 35 views
1
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定義了一個下標運算符。由於@參數pos是size_t類型,我無法檢查用戶是否已傳遞正值或負值。 Howerver我嘗試寫的代碼做的,而不是束縛檢查和它的作品:添加size_t類型值的指針

 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 
+1

FWIW,這是一個壞主意。錯誤指針是代碼中的一個** bug **,它們不應該導致異常(這是一個意外的,但並非沒有準備就緒的情況)。不應該爲壞指針做好準備,應該阻止它們。如果你想改善你的代碼的可調試性,你可以使用'assert'來代替(或者事實上,依賴於系統的調試器)。另外,'const_cast'在這裏只是語義錯誤。不要存儲指向'const'的指針,存儲'const'指針。最後,'beg'從不使用。去掉它。 –

+0

@Konrad Rudolph:感謝您的評論:) – Tianyi

回答

2

該作品因爲n例外值被轉換爲無符號值。你的機器架構可能使用二進制補碼爲負值,所以在-2結果值:

0xfffffffe (assuming 32-bit) 

當您添加到beg,它環繞並提供beg大於或等於2,具有從中減去2的效果。因此,儘管指數非常大,但它基本上已經執行了減法。如果beg的值是10,則錯誤將是「過去的結束」。

+1

從signed到unsigned的轉換不依賴於機器體系結構:「如果目標類型是無符號的,則結果值是與源整數相同的最小無符號整數(模2n其中n是用於表示無符號類型的位數)[注:在二進制補碼錶示中,這種轉換是概念性的,並且位模式沒有變化(如果沒有截斷)。 –

1

形式上,比較beg + posbeg有未定義的行爲,如果beg + pos是開始於beg陣列外(這是略微簡化,但足夠用於該討論)。更好地檢查不良索引將是:

if (end - beg <= pos) 

但是,這並不回答這個問題。將小的負值轉換爲size_t會產生較大的正值;將它們視爲偏移量會產生一個遠遠超過數組末尾的指針,因此檢查結果是否在界限內會發現此問題以及「普通」值,這些值超出了最終值。