JavaScript is required to for searching.
ナビゲーションリンクをスキップ
印刷ビューの終了
Oracle Solaris Studio 12.3 Discover および Uncover ユーザーズガイド     Oracle Solaris Studio 12.3 Information Library (日本語)
search filter icon
search icon

ドキュメントの情報

はじめに

1.  概要

2.  メモリーエラー探索ツール (Discover)

Discover を使用するための要件

バイナリは正しく準備される必要がある

プリロードまたは監査を使用するバイナリは使用できまい

標準メモリー割り当て関数を再定義するバイナリを使用できる

クイックスタート

準備されたバイナリの計測

共有ライブラリのキャッシュ

共有ライブラリの計測

ライブラリの無視

コマンド行オプション

出力オプション

計測オプション

キャッシュオプション

その他のオプション

bit.rc 初期化ファイル

SUNW_DISCOVER_OPTIONS 環境変数

SUNW_DISCOVER_FOLLOW_FORK_MODE 環境変数

計測済みバイナリの実行

Discover レポートの分析

HTML レポートの分析

「エラー (Errors)」タブの使用法

「警告 (Warnings)」タブの使用法

「メモリーリーク (Memory Leaks)」タブの使用法

コントロールパネルの使用法

ASCII レポートの分析

メモリーアクセスエラーと警告

メモリーアクセスエラー

ABR

ABW

BFM

BRP

DFM

FMR

FMW

FRP

IMR

IMW

OLP

PIR

SBR

SBW

UAR

UAW

UMR

メモリーアクセスの警告

AZS

Discover エラーメッセージの解釈

部分的に初期化されたメモリー

スペキュレイティブロード

未計測コード

Discover 使用時の制限事項

注釈付きコードのみが計測される

機械命令はソースコードとは異なる場合がある

コンパイラオプションは生成されたコードに影響を及ぼす

システムライブラリは報告されたエラーに影響を及ぼす可能性がある

カスタムメモリー管理はデータの正確さに影響を及ぼす可能性がある

静的および自動配列範囲外は削除できない

3.  コードカバレッジツール (Uncover)

索引

Discover エラーメッセージの解釈

場合によっては、Discover は実際にはエラーでないエラーを報告することがあります。そのようなケースは、擬陽性と呼ばれます。Discover は計測時にコードを分析し、同様なツールと比較して、擬陽性の発生を削減しますが、依然として発生する場合があります。次のセクションでは、Discover レポートでの擬陽性を特定し、可能であれば回避できるようにするヒントを提供します。

部分的に初期化されたメモリー

C および C++ のビットフィールドでは、コンパクトなデータ型を作成できます。例:

struct my_struct {
  unsigned int valid : 1;
  char         c;
};

この例では、構造メンバー my_struct.valid はメモリー内の 1 ビットのみ取得します。ただし、SPARC プラットフォーム上では、CPU はバイト単位でのみメモリーを変更できるため、struct.valid を含むバイト全体が構造メンバーにアクセスまたは変更するためにロードされる必要があります。また、コンパイラは 1 度に数バイト (たとえば、4 バイトの機械語) をロードする方がより効率的であることがわかる場合があります。Discover がこのようなロードを検出する場合、追加情報なしに、すべて 4 バイトが使用されると仮定します。また、たとえば、フィールド my_struct.valid は初期化されたが、フィールド my_struct.c は初期化されず、両方のフィールドを含む機械語がロードされた場合、Discover は部分的に初期化されたメモリーからの読み取り (PIR) にフラグを立てます。

擬陽性の別のソースはビットフィールドの初期化です。1 バイト部分を書き込むには、コンパイラは最初にバイトをロードするコードを生成する必要があります。バイトが読み取るより前に書き込まれていない場合、結果は非初期化メモリーからの読み取りエラー (UMR) となります。

ビットフィールドの擬陽性を回避するには、コンパイル時に -g オプションまたは -g0 オプションを使用します。これらのオプションは、Discover に追加のデバッグ情報を提供し、ビットフィールドのロードと初期化を特定するのに役立ち、多くの擬陽性を削除します。何らかの理由で -g オプションを使用してコンパイルできない場合は、memset() などの関数を使用して構造を初期化します。例:

...
struct my_struct s;
/* Initialize structure prio to use */
memset(&sm 0, sizeof(struct my_struct));
...

スペキュレイティブロード

コンパイラは、ロードの結果がすべてのプログラムパスで有効ではない条件下の不明なメモリーアドレスからロードを生成する場合があります。このようなロード命令は分岐命令の遅延スロットに配置できるため、この状況は SPARK プラットフォーム上で発生する場合がよくあります。たとえば、ここに C コードフラグメントがあります。

int i'
if (foo(&i) != 0) { /* foo returns nonzero if it has initialized i */
  printf("5d\n", i);
}

このコードから、コンパイラは次のコードに等しいコードを生成できます。

int i;
int t1, t2'
t1 = foo(&i);
t2 = i; /* value in i is loaded */
if (t1 != 0) {
  printf("%d\n", t2);
}

この例では、関数 foo()0 を返し、i を初期化しないと仮定します。i からのロードは、依然として生成されますが、使用されません。しかし、ロードは Discover によって確認され、非初期化変数のロード (UMR) を報告します。

Discover はデータフロー分析を使用して、可能な場合には常にそのようなケースを特定しますが、検出できない場合もあります。

最適化レベルを低くしてコンパイルすることによって、これらのタイプの擬陽性の発生を削減できます。

未計測コード

Discover はプログラムの 100% を計測できない場合があります。おそらく、コードの一部がアセンブリ言語のソースファイルまたは再コンパイルできないサードパーティのライブラリから来ているため、計測できない場合があります。Discover には、未計測コードがアクセスまたは変更しているメモリーブロックの知識がありません。たとえば、サードパーティの共有ライブラリから得られる関数がのちにメイン (計測済み) プログラムによって読み取られるメモリーブロックを初期化すると仮定します。Discover はメモリーがライブラリで初期化されていることを認識していないため、後続の読み取りにより、非初期化メモリーエラー (UMR) が生成されます。

このような場合の解決策を提供するため、Discover API には次の関数が含まれています:

void __ped_memory_write(unsigned long addr, long size, unsigned long pc);
void __ped_memory_read(unsigned long addr, long size, unsigned long pc);
void __ped_memory_copy(unsigned long src, unsigned lond dst, long size, unsigned long pc);

プログラムから API 関数を呼び出し、Discover にメモリー領域への書き込み (__ped_memory_write ()) やメモリー領域からの読み取り (__ped_memory read()) などの特定のイベントを知らせることができます。どちらの場合も、メモリー領域の開始アドレスは、addr パラメータで渡され、そのサイズは size パラメータで渡されます。pc パラメータを 0 に設定します。

__ped_memory_copy 関数を使用して、Discover にメモリーがある場所から別の場所にコピーされていることを知らせます。ソースメモリーの開始アドレスは src パラメータで渡され、宛先領域の開始アドレスは dst パラメータで渡され、サイズは size パラメータで渡されます。pc パラメータを 0 に設定します。

API を使用するには、プログラムでこれらの関数を weak と宣言します。たとえば、ソースコードに次のコードフラグメントを含めます。

#ifdef __cplusplus
extern "C" {
#endif

extern void __ped_memory_write(unsigned long addr, long size, unsigned long pc);
extern void __ped_memory_read(unsigned long addr, long size, unsigned long pc);
extern void __ped_memory_copy(unsigned long src, unsigned long dst, long size, unsigned long pc);

#prgama weak __ped_memory_write
#pragma weak __ped_memory_read
#pragma weak __ped_memory_copy

#ifdef __cplusplus
}
#endif

API 関数は内部 Discover ライブラリで定義され、計測時にプログラムとリンクされます。ただし、プログラムが計測されない場合、このライブラリはリンクされず、API 関数へのすべての呼び出しによってアプリケーションがハングアップします。そのため、Discover 下でプログラムを実行していない場合は、これらの関数を無効にする必要があります。または、API 関数の空の定義を使用して動的ライブラリを作成し、それをプログラムとリンクすることができます。この場合、Discover を使用しないでプログラムを実行する場合は、ライブラリが使用されますが、Discover 下で実行する場合は、真の API 関数が自動的に呼び出されます。