關於一般性保護錯誤的原因和解決辦法

2021-07-25 02:17:51 字數 2353 閱讀 9344

一 什麼是一般性保護錯誤(gp)?

一般性保護錯誤(general protect簡稱gp),通常只是windows下的乙個術語,我們現在也常把它引用到unix下指程式的崩潰。

本文主要**windows下面程式gp的原因,預防和解決辦法。

二  gp的原因

win32作業系統在發現某應用程式企圖訪問不屬於自己的非法的記憶體區域時,將觸發一般性保護錯誤,立刻終止該應用程式,防止該程式破壞其他程式的記憶體資料,對其他程式造成不良影響。

如果該機器上裝dr washington軟體,該軟體將捕捉該錯誤,並出錯時的應用程式記憶體位址情況抓下來,但實際上要分析的話,恐怕需要專門的工具。

如果沒有裝dr軟體,通常會彈出乙個對話方塊,類似提示為該應用程式非法的訪問了0xefedcd的錯誤出來。

如果應用程式為debug版本,這時候彈出的對話方塊可能會友善一點點,有時會彈出乙個assert對話方塊,要你除錯還是放棄來著。

以下具體分析導致gp的種種原因:

1 編譯器的bug或編譯開關設定不當。

已經有文件和實踐證明,vc6.0編譯器在缺少補丁的情況,使用最大速度優化將導致程式在某種特殊情況下gp。

編譯開關建議一律採用單位元組對齊,否則介面程式越多,不一致的對齊方式最後有可能導致gp。

2 庫檔案或其他配置支撐檔案缺少,或者不匹配。

比如原來正常工作的應用程式和配套的dll,將其中乙個dll用另乙個同名但版本不同的dll替換將導致gp。這是很容易理解的,不同dll的函式記憶體映象是不同,應用程式企圖通過乙個非法的位址訪問函式自然會gp。

另外乙個常見的例子時winsock的支援版本不一致。使用了winsock的高階特性,但支援庫卻跟不上。

還有乙個例子也很有代表性,幾個軟體使用乙個共用的庫檔案,其中乙個軟體公升級後,偷偷將該庫檔案給替換了,導致其他軟體不能正常使用。

3 不安全的api函式

分為幾類說明

3.1 字串函式

strlen win32下面傳入不能為空

sprintf 前面的%和後面的引數不匹配。

建議使用snprintf而不是sprintf,因為前者判斷緩衝溢位,後者不判斷。

strcat,在後面疊加時,一定要判斷緩衝大小。

strcpy

3.2 記憶體函式

memset,memcpy等,一定要判斷記憶體位址有效性,以及大小等。

3.3 時間函式

localtime 不能傳入-1

3.4 其他入參有特殊要求的函式,使用時請仔細檢視msdn。

4 陣列訪問越界,包括上下界。

5 訪問到malloc所分配的記憶體區域後面的記憶體。

6 用malloc分配了記憶體,卻不檢驗其合法性。

比如 用子函式分配堆上記憶體,在子函式中雖然有出錯判斷,但呼叫函式卻根本沒有考慮。

雖然從一般情況下考慮,windows採用虛擬記憶體方式,一般不會malloc失敗,但是在系統非常繁忙且硬碟空間狹小的情況,一次性分配巨量堆上記憶體,仍然會可能會malloc失敗

7 已經釋放malloc分配的記憶體,卻沒有把malloc返回的指標置為null,另乙個地方企圖使用該指標指向的記憶體資料。

8企圖重複釋放malloc分配的記憶體。

9 兩個函式使用乙個全域性資料結構,結構中有指標成員,該指標指向第乙個函式在在堆疊上分配的一塊記憶體,第二個函式企圖通過該指標成員訪問那塊記憶體。

10 第乙個函式返回乙個堆疊上的記憶體位址為返回值,第二個函式企圖使用第乙個函式的返回值來獲取該記憶體上的資料。堆疊上分配的記憶體位址,在函式退出時,該空間內的資料隨時可能被其他函式覆蓋,所以為不可用資料。

11 數值被0除。(此屬於溢位錯誤,不屬於訪問記憶體失敗,放在這只是為了提醒)

12 企圖改變儲存在靜態儲存區的常量字串字面值。

13 企圖對右值賦值。

14 企圖使用乙個空指標,經常出現在函式中使用入口指標時不進行判斷。

15 訊息介面定義不一致,經常出現在各界面程式的標頭檔案定義不一致,導致非法的訊息操作。比如 位元組序轉換時由於對方送來的訊息比預期的小,就會訪問到後面的記憶體區域,導致gp。

17 病毒或不同格式檔案系統反覆拷貝程式導致檔案被破壞,注意檢查檔案大小和時間是否變化。

16 作業系統的bug,通常作業系統和複雜軟體比如oralce資料庫等的相容性問題,這種問題,只有到微軟的站點和相關公司的站點多下點補丁吃吧。

三解決辦法

1 預防性校驗 包括指標有效性判斷,函式入參判斷。

2 利用斷言assert發現問題。

3 除錯時分為兩種現象:比如api,陣列越界這種問題單步跟蹤很快可以發現問題,象第五種有時表現出來非常奇怪,一會在這函式,一會那函式出現,利用函式體簡化的方法,可排除干擾項。

注意檢視堆疊記錄,函式呼叫順序。

4 利用除錯日誌。

5 利用程式崩潰記憶體映像分析。

6 採用環境比較法。

GDI 中發生一般性錯誤

替代方法 建立非索引映像。建立索引映像。這兩種情況下,原始 位圖 上呼叫 bitmap.dispose 方法刪除該檔案上鎖或刪除要求,流或記憶體保持活動。建立非索引影象 即使原始映像被索引格式中該方法要求新影象位於每畫素 超過 8 位 非索引畫素格式。此變通方法使用 graphics.drawima...

GDI 中發生一般性錯誤 的解決辦法

bitmap 物件或乙個 影象 物件從乙個檔案,構造時該檔案仍保留鎖定對於物件的生存期。因此,無法更改影象並將其儲存回它產生相同的檔案。建立乙個bitmap型別的bmp變數來讀取檔案。bitmap bmp new bitmap openfiledialog1 filename 新建第二個bitmap...

錢包的一般性介紹

最近有很多朋友問我關於錢包的一些知識,為避免重複回答,下文做簡要一般性介紹,以後有人再問就直接給本文章的鏈結 顧名思義,錢包是用來儲存錢的。但在數字貨幣的世界中,錢包裡面並沒有 錢 錢包賬戶裡有多少 錢 都是記錄在區塊鏈上的,錢包裡只是儲存了賬戶對應的 私鑰,賬戶是從私鑰相應的公鑰衍生出來的。只要有...