C++ 處理非空的錯誤指標
對於非空的錯誤指標導致的崩潰,不能用常用的try{}catch{}進行處理,在C++中,這種方法只能處理異常,但對於空指標、除以0這些操作,不能算是異常,而是錯誤,是不能捕獲並處理的;
非空的錯誤指標,通常是由試圖訪問了非法的記憶體或者寫入了非法的記憶體導致的,比如說:訪問損壞的dump檔案裡面的內容,會導致讀取記憶體或模組列表出錯;這時可選擇使用Windows API函式來進行處理;
判斷呼叫程序是否擁有對指定字串指標的讀取許可權,函式原型如下:
BOOL IsBadStringPtr(
LPCTSTR lpsz,
UINT_PTR ucchMax);
引數:
lpsz: 輸入引數,指向字串。
ucchMax:輸入引數,讀取字串的最大長度。
返回值:
返回BOOL值,表示當前程序是否擁有字串指標指向的字串的度操作許可權。
IsBadWritePtr
判斷呼叫程序是否擁有對指定地址段記憶體的寫操作許可權,函式原型如下:
BOOL IsBadWritePtr(
LPVOID lp,
UINT ucb);
引數:
lp: 輸入引數,指向起始記憶體地址。
ucb: 輸入引數,從起始記憶體地址開始的記憶體塊的長度。
返回值:
返回BOOL值,表示當前程序是否擁有字串指標指向的字串的寫入許可權。
IsBadWritePtr BOOL IsBadWritePtr( LPVOID lp, UINT ucb );
驗證呼叫程序具有寫訪問許可權的指定範圍的記憶體。
lp 第一個位元組的記憶體塊的指標。
ucb 指定的大小,單位為位元組的記憶體塊。如果此引數為零,則返回值為零。
返回值
零 呼叫程序在指定的記憶體範圍具有寫訪問許可權的所有位元組。
非零 呼叫程序在指定的記憶體範圍內沒有寫訪問許可權的所有位元組。
IsBadReadPtr
函式原型:
BOOL IsBadReadPtr(CONST VOID *lp,UINT_PTR ucb);
引數:
lp 表示要檢查的記憶體指標
ucb 要檢查的記憶體塊的大小
返回:
如果呼叫程序有許可權訪問該記憶體,返回0
否則,返回非0
說明:
該函式檢查呼叫程序是否有讀取指定記憶體的內容的許可權,微軟提供的32位作業系統下的API
BOOL IsBadReadPtr(
const VOID* lp,
UINT_PTR ucb
);
驗證呼叫程序具有讀訪問許可權的指定範圍的記憶體。
lp 第一個位元組的記憶體塊的指標。
ucb 指定的大小,單位為位元組的記憶體塊。如果此引數為零,則返回值為零。
返回值
零 呼叫程序在指定的記憶體範圍具有讀訪問許可權的所有位元組。
非零 呼叫程序在指定的記憶體範圍內沒有讀訪問許可權的所有位元組。
關於如何獲取指標記憶體塊的長度:
這裡介紹一個不常見到的函式,即:_msize()。其原型為:size_t _msize( void * memblock );
一般我們要返回某個型別的資料所佔用的記憶體首先是考慮 sizeof() 和 strlen() 函式,但對於用 new 分配出來的記憶體來說如:char * pc = new char[10] ; 想返回 pc 所指向的記憶體的大小,sizeof(pc), 或strlen(pc) 都是得不到所需要結果的,因為 sizeof() 返回的是指標本身所佔用記憶體的大小,strlen() 只能用char*做引數,且必須是以''\0''結尾的。
而_msize() 函式則可以返回用 new 方式分配出來的記憶體大小。如下所示:
char * pc = new char[10] ;
int n = _msize(pc) / sizeof(char);
最後得到的結果是 n = 10。
(1)函式原型
size_t _msize(
void* memblock
);
(2)函式說明
1)引數memblock為一個堆記憶體塊的地址。不能傳入棧上的地址(例如a[10],_msize(a))
2)函式返回指標所指記憶體塊的大小。malloc分配的函式返回的地址不包含首部,因此使用_msize()函式測得的也不包含首部大小。
注意:這個函式需要標頭檔案:#include<malloc.h>對於不能讀取到的堆記憶體無法使用,否則會導致崩潰。