本ページは公開が終了したページの複製であり、掲載時点での情報です。本ページに記載されている内容について各所に問い合わせることはご遠慮下さい。

[SDK16] 一般保護違反発生の原因、及びデバッグ手法

PWJ2045 - 95/10

この資料は以下の製品について記述したものです。

  

概要

この資料は、Microsoft Windows Version 3.1 (以下 Windows)用のプログラム実行時に発生する一般保護違反 (GPF:General Protection Fault) の原因とデバッグ方法を紹介したものです。

  

詳細

プログラム実行時に発生する一般保護違反には、様々な原因が考えられ一概にこれと決めつけられるものはありません。ここでは、一般的に発生しやすいケースとデバック手法を紹介いたします。

  

原因

1.Windows API のパラメータセット、使用方法の矛盾

Windows API に指定するパラメータセット、使用方法に矛盾がある時一般保護違反が発生する場合があります。

  

TextOut((HDC) hinstCurrent, 0, 0,(LPCSTR) buff, strlen(buff)); // 間違ったハンドル
// インスタンス 正しくは hWnd 等のウインドウハンドル

パラメータセットに矛盾が無い場合にも、その Windows API を 呼び出すタイミングにより一般保護違反が発生する場合があります

  

:
GlobalFree( hglb ); // 解放するオブジェクトのハンドル
:
GlobalFree( hglb ); // プログラムミスで再び同じハンドルに対して解放を
// 行った。

2.無効なポインタに対する書き込み及び読み込み

初期化されていないポインタや配列範囲を越えたポインタに書き込み及び読み込みを行った時一般保護違反が発生する場合があります

  
例1
int *p;
if ( 真にならない )
{
p = (int *) LocalAlloc( LPTR, sizeof( int ));
}
*p = 1; // 実体のないポインタへの代入

例2
#define MSIZE 8
int boo[MSIZE];
int i;

i = MSIZE;
boo[i] = 1; // boo[8] = 1; 配列範囲を越えた代入

3.ゼロ除算オーバーフロー

分母がゼロの時の除算で一般保護違反が発生します。

  

int i;
for ( i = 0 ; i < NMAX ; i++ )
{
data = data / i; // i = 0 の時 一般保護違反が発生します。
}

対策

A.Windows のデバッグバージョンを使用する

問題1の原因を検査するのに有効です。

  

Windows システムのデバッグバージョンをインストールし SDK 付属サンプル DBwin を立ち上げることにより細かい診断メッセージを取得できます。

  

以下の例では SDK付属サンプル GENERIC を変更しエラーを発生させた例です。

  
:
switch (message) {
case WM_COMMAND:
/* メッセージ: アプリケーションメニューからのコマンド */
if (wParam == IDM_ABOUT) {
GlobalFree(0); // 無効なメモリハンドル
break;
}
:
;

#### DBwin でのエラーメッセージ ####

err GENERIC GLOBALFREE+15: Invalid global handle: 0x0000

FatalExitコード = 0x6022
Abort, Break, Exit or Ignore?

このメッセージにより プログラム GENERIC 内の GLOBALFREE に問題がある事が予想できます。

詳しい使用方法などは、マニュアル”プログラミングツールズ”の

”Windowsデバックバージョン”をご覧ください

  

B.ワトソン博士を使用する

問題2、3の原因を検査するのに有効です。

  

Windows 付属のワトソン博士を使用するには、Windows ディレクトリの Win.ini ファイルの [ワトソン博士] セクションにエントリを設定し、その後、DRWATSON.EXE を起動します。この時、問題を発見しやすくする為予め関連の無いアプリケーションは終了させておいてください。次に、プログラムを実行し問題を再現させ一 般保護違反を起こしてください。一般保護違反発生時に、ワトソン博士は問題データをログファイルに記録します

  


#### WIN.INI ####
:
:
[ワトソン博士] <----- 追加 // マニュアル[SDKプログラミングツールズ]に
ShowInfo = dis err par sur // ある[Dr.Watson]は誤記です。
TrapZero=1
:
:

#### DRWATSON.LOG ####

Start ワトソン博士 0.80 - Mon Mar 20 16:17:46 1995
****************************************************************************
ワトソン博士 0.80 Failure Report - Mon Mar 20 16:17:57 1995
GENERIC had a 'Divide by 0' fault at GENERIC 1:0170
$tag$GENERIC$Divide by 0$GENERIC 1:0170$idiv word ptr [0040]$Mon Mar 20 \
16:17:57 1995

CPU Registers (regs)
ax=0001 bx=3e4c cx=0064 dx=0000 si=15fe di=180b
ip=0170 sp=15d8 bp=15da O- D- I+ S- Z+ A- P+ C-
cs = 2307 806fabe0:097f Code Ex/R
ss = 35af 80af7d80:1a3f Data R/W
ds = 35af 80af7d80:1a3f Data R/W
es = 35af 80af7d80:1a3f Data R/W

CPU 32 bit Registers (32bit)
eax = 00000001 ebx = 00003e4c ecx = 00000064 edx = 00000000
esi = 000015fe edi = 0000180b ebp = 000015da esp = 800115c8
fs = 0000 0:0000 Null Ptr
gs = 0000 0:0000 Null Ptr
eflag = 00000202

Instruction Disassembly (disasm)
2307:0167 83 f9 64 cmp cx, 64
2307:016a 75 14 jnz short 0180
2307:016c b8 0001 mov ax, 0001
2307:016f 99 cwd
(GENERIC:1:0170) <------ この場所でゼロ除算が発生
2307:0170 f7 3e 0040 idiv word ptr [0040]
2307:0174 a3 0040 mov [0040], ax
2307:0177 33 c0 xor ax, ax
2307:0179 99 cwd


#### GENERIC.MAP ####

0000:0000 Imp WAITEVENT (KERNEL.30)
0000:0000 Imp GETMESSAGE (USER.108)
0000:0000 Imp FATALAPPEXIT (KERNEL.137)
0000:9876 Abs __acrtmsg
0000:9876 Abs __acrtused
0000:9876 Abs __fptaskdata
0000:D6D6 Abs __aDBused
0000:D6D6 Abs __aDBdoswp
0001:0010 WINMAIN
0001:0082 _InitApplication
0001:00E6 _InitInstance
0001:013A MainWndProc <--- ここで About が発生していることから
このモジュールに問題があるのが解かります。
0001:0198 About
0001:01D2 __wflags
0001:01DA __astart
0001:0273 __nomain
0001:027A __stubmain

以上の内容から問題が、MainWndProc 内部にある事が予想できます。

  

一般保護違反が、ユーザプログラム内でなくWindowsカーネル内で起こる場合もあります。この場合、DRWATSON.LOG ファイルのスタック履歴を参照し、最後に呼ばれたユーザプログラムの場所を調査してみてください。

詳しい使用方法などは、マニュアルの”システムエラーの解析:ワトソン博士”をご覧ください。

  

その他

(C)1995 Microsoft Corporation. All rights reserved.

マイクロソフト株式会社 テクニカル サポート


UP
UP
Home
HOMEPAGE
inserted by FC2 system