Yggdrasil Seeds : 拙作ソフトウェアとか : Language Select : Denullpo, the pointer checker : Denullpo

Denullpo


最小限の使い方

それぞれのC/C++ソースで denullpo.h をインクルードする。ただし、何も設定していない場合は、全ての機能が無効になる。
設定は全て denullpo.h をインクルードする前に所定の定数を定義することで反映される。
DENULLPO_TRAP
これが定義されていれば、エラー検出コールバックが有効となる。
DENULLPO_SKIP
これが定義されていれば、エラー検出を行う。
DENULLPO_TRAP も DENULLPO_SKIP も定義されていなければ、エラー検出を行わない。
DENULLPO_4CC
インスタンスが有効であることを示す値。
定義されていなくても、自動的に一定値が定義される。
ポインタのチェックを行うべき箇所で、 denullpo() にポインタを渡す。
このとき、ポインタがNULLであれば、Denullpoは設定されたエラー処理を行う。
Sample Code
/*=== denullpo()でNULLポインタへのアクセスを回避する ===*/
#include <stdio.h>
/*=== denullpo()をインクルードする前に設定する必要がある ===*/
/*=== この行をコメント化すると、Denullpoの処理を除去できる ===*/
#define DENULLPO_SKIP
#include "denullpo.h"

int main(int argc,char *argv[]){
void* p=NULL;
int err=0;

p=malloc(128);
/*=== ポインタのチェック結果で処理を分ける ===*/
if(denullpo(p)){
/*=== 異常時の処理 ===*/
fprintf(stderr,"this is nullpo\n");
err=1;
}
else{
/*=== 正常時の処理 ===*/
// :
// :
// :
free(p);
p=NULL;
}
return err;
}


インスタンスの有効性調査

Denullpoは、クラスや構造体にマジックコード用のメンバを付け加えることでインスタンスの有効性を調べることができる。
チェック対象のクラスや構造体には、 DENULLPO_INITCHECKER でマジックコードの書き込み先を定義する。
インスタンスを生成したとき、 denullpo_setinit() を呼んでインスタンスが有効になったことを示す。
そしてインスタンスを破棄するとき、 denullpo_setpurge() を呼んでインスタンスが無効になったことを示す。
ポインタのチェックを行うべき箇所で、 denullpo2() にポインタを渡す。
このとき、ポインタが不正であれば、Denullpoは設定されたエラー処理を行う。
Sample Code
/*=== 不正なインスタンスのメソッド呼び出しを阻止する ===*/
#include <stdio.h>
#define DENULLPO_SKIP
#include "denullpo.h"

class FOO{
public:
/*=== クラスにマジックコード書き込み場所を確保する ===*/
DENULLPO_INITCHECKER;

FOO(){
/*=== 初期化したことを示すマジックコードを書き込む ===*/
denullpo_setinit(this);
}

~FOO(){
/*=== 終了したことを示すマジックコードを書き込む ===*/
denullpo_setpurge(this);
}

void exec(){
/*=== このメソッドがdenullpo_setinit()とdenullpo_setpurge()の間以外から呼ばれたらエラーとして扱う ===*/
if(denullpo2())return;
// :
// :
// :
}
};


エラー検知コールバック

通常、denullpo()denullpo2()は、エラーを検出したときすぐに結果を返す。
denullpo_settrap()によりコールバックが設定されている場合、エラーを検出したときに呼び出され、その結果が反映される。
コールバックを有効とするには、denullpo.hをインクルードする前にDENULLPO_TRAPを定義しなければならない。
Sample Code
/*=== 不正なポインタのエラー処理を独自に実装する ===*/
#include <stdio.h>
/*=== コールバックを有効にするための設定 ===*/
#define DENULLPO_TRAP
#include "denullpo.h"

int err=0;

/*=== エラー検出時の処理 ===*/
static unsigned __cdecl hook(void *p,eDenullpoReason reason){
fprintf(stderr,"nullpo is hooked\n");
err=1;

/*=== ここの返値が、そのままdenullpo()の返値となる。 ===*/
return 1;
}

int main(int argc,char *argv[]){
void* p=NULL;

/*=== コールバックの設定 ===*/
denullpo_settrap(hook);

p=malloc(128);
/*=== ポインタがNULLなら、設定されたコールバックを実行 ===*/
if(!denullpo(p)){
/*=== 正常時の処理 ===*/
// :
// :
// :
free(p);
p=NULL;
}
return err;
}


詳細

定義類

eDenullpoReason
hDenullpoTrapコールバックで通知されるエラー情報。
DENULLPO_NULL
調査対象のポインタがNULLであることを示す。
DENULLPO_INVALID
調査対象のインスタンスが無効であることを示す。

コールバック型

unsigned (*hDenullpoTrap)(void* p, eDenullpoReason reason)
エラー検知コールバック
denullpo_settrap()で関数を設定すると、エラーが検知されたときに呼ばれる。
引数
p
調査対象のポインタ
reason
エラー発生根拠
返値
0
エラー要因は、解決された。
1
エラー要因は、依然として残っている。

関数類

hDenullpoTrap denullpo_gettrap()
エラー検知コールバックの取得
返値
現在の設定値
hDenullpoTrap denullpo_settrap(hDenullpoTrap trap)
エラー検知コールバックの設定
引数
trap
コールバックとして扱う関数
返値
現在の設定値
補足
この関数は、スレッドセーフではない。
unsigned denullpo_exectrap(void* p, eDenullpoReason reason)
エラー検知コールバックを呼ぶ。
引数
p
調査対象のポインタ
reason
エラー発生根拠
返値
0
エラー要因は、解決された。
1
エラー要因は、依然として残っている。
unsigned denullpo_getinit(any* p)
インスタンスチェッカの値を得る
引数
p
対象インスタンス
返値
インスタンスチェッカ現在値
void denullpo_setinit(any* p)
インスタンスが初期化されたことをインスタンスチェッカに通知する
引数
p
対象インスタンス
補足
denullpo2()の対象となる各インスタンスに対し、このマクロを呼ぶ必要がある。
void denullpo_setpurge(any* p)
インスタンスが終了されたことをインスタンスチェッカに通知する
引数
p
対象インスタンス
補足
denullpo2()の対象となる各インスタンスに対し、このマクロを呼ぶ必要がある。
unsigned denullpo_chkinit(any* p)
インスタンスが初期化されているかを調べる
引数
p
対象インスタンス
返値
0
異常なし
1
異常あり
補足
通常、このマクロは直接呼ばない。インスタンスを調べるには、denullpo2()を使う。
int denullpo(any* p)
ポインタがNULLであるかを調べる
引数
p
対象ポインタ
返値
0
NULLではない
1
NULLである
補足
denullpo_settrap()でコールバック関数を設定してあれば、エラー検出時にその関数が呼び出される。
int denullpo2(any* p)
インスタンスが異常であるかを調べる
引数
p
対象インスタンス
返値
0
異常なし
1
異常あり
補足
denullpo_settrap()でコールバック関数を設定してあれば、エラー検出時にその関数が呼び出される。
この関数を扱うには、適切な位置でdenullpo_setinit()denullpo_setpurge()を呼ぶ必要がある。

今後の予定


DSHs PHPlib v0.1.0 (C)2006-9 Denullpo Smasher Hammerson