Solaris 動的トレースガイド

ポインタの安全性

C や C++ の知識をお持ちのユーザーは、前の節をお読みになって、ポインタの使い方を間違えるとプログラムがクラッシュするのではないかと、少し不安になったかもしれません。DTrace は堅牢で安全な環境であるため、このような間違いのある D プログラムを実行しても、プログラムがクラッシュする心配はありません。作成した D プログラムにバグがあっても、無効な D ポインタアクセスが原因で DTrace やオペレーティングシステムカーネルに障害やクラッシュが起きることはありません。DTrace は、無効なポインタアクセスを検出すると、計測機能を無効にし、デバッグに役立つ情報を報告します。

Java プログラミングの経験をお持ちであればご存知でしょうが、Java 言語では、このような安全面の理由から、ポインタはサポートされていません。D では、C で記述されたオペレーティングシステムの実装の本質的な部分として、ポインタを使用する必要があります。しかし、DTrace には、Java プログラミング言語と同様の保護機構が実装されているため、プログラムにバグがあっても、そのプログラム自体やその他のプログラムに危害を与えることはありません。DTrace のエラー報告機能は、Java プログラミング言語の実行環境と同じように、プログラミングエラーを検出し、例外を報告します。

以下では、DTrace のエラー処理およびエラー報告機能について確認するため、ポインタを使って、意図的に不正な D プログラムを作成してみましょう。エディタで以下の D プログラムを入力し、badptr.d という名前のファイルに保存してください。


例 5–1 badptr.d: DTrace のエラー処理機能のデモ

BEGIN
{
	x = (int *)NULL;
	y = *x;
	trace(y);
}

badptr.d プログラムで作成されている D ポインタ x は、int へのポインタです。このポインタには、特殊かつ無効なポインタ値 NULL が割り当てられていますが、この値はアドレス 0 を表す組み込みの別名です。慣例上、アドレス 0 は常に無効と定義されます。このため、C プログラムや D プログラムでは、NULL は標識値として使用できます。このプログラムでは、キャスト式により、NULL が整数ポインタに変換されています。このポインタは式 *x によって間接参照され、その結果が別の変数 y に割り当てられます。その後、この変数 y のトレースが試みられます。この D プログラムを実行すると、y = *x という文が実行されたところで無効なポインタアクセスが検出され、エラーが報告されます。


# dtrace -s badptr.d
dtrace: script '/dev/stdin' matched 1 probe
CPU     ID                    FUNCTION:NAME
dtrace: error on enabled probe ID 1 (ID 1: dtrace:::BEGIN): invalid address
(0x0) in action #2 at DIF offset 4
dtrace: 1 error on CPU 0
^C
#

プログラムで無効なポインタを使用した場合、「配置エラー」の問題が起きることもあります。構造上、整数をはじめとする基本データオブジェクトは、そのサイズに従ってメモリー内に配置されます。たとえば、2 バイトの整数は 2 の倍数のアドレス、4 バイトの整数は 4 の倍数のアドレスというように配置されます。4 バイトの整数のポインタを間接参照するとき、このポインタが 4 の倍数以外の無効な値のアドレスに配置されていると、アクセスに失敗し、配置エラーが返されます。たいていの場合、D の配置エラーは、D プログラム内のバグによってポインタの値が無効になったか、壊れていることを示します。配置エラーの例として、ソースコード badptr.d で、NULL の代わりにアドレス (int *)2 を指定してみてください。int は 4 バイトで、2 は 4 の倍数ではないので、式 *x は DTrace 配置エラーになります。

DTrace のエラー機構の詳細は、ERROR プローブ」を参照してください。