discover レポートは、ソースコードで効果的に自動補完して問題を修正する情報を提供します。
デフォルトでは、レポートは output-file.html に HTML 形式で書き込まれます。output-file は、計測済みバイナリのベース名です。ファイルは、計測済みバイナリを実行する作業ディレクトリに配置されます。
バイナリを計測する際には、–H オプションを使用して、HTML 出力を指定されたファイルに書き込むように要求するか、–w オプションを使用して、テキストファイルに書き込むように要求できます。
バイナリを計測したあと、その後のプログラム実行でレポートを異なるファイルに書き込む場合は、SUNW_DISCOVER_OPTIONS 環境変数でレポートの –H および –w オプションの設定を変更できます。詳細は、SUNW_DISCOVER_OPTIONS 環境変数を参照してください。
HTML レポート形式では、プログラムの対話型分析が提供されます。HTML 形式のデータは、電子メールを使用するか、Web ページ上に配置して、開発者間で容易に共有できます。この形式と JavaScript インタラクティブ機能と組み合わせると、discover のメッセージを検索する便利な方法が提供されます。
このセクションでは、HTML レポートについて説明します。ここで説明するタブは次のとおりです。
「エラー」タブ、「警告」タブ、および「メモリーリーク」タブでは、エラーメッセージ、警告メッセージ、およびメモリーリークレポートをそれぞれナビゲートできます。
左側のコントロールパネルでは、右側に現在表示されているタブの内容を変更できます。コントロールパネルの使用法を参照してください。
ブラウザで最初に HTML レポートを開くと、「エラー」タブが選択され、計測済みのバイナリの実行中に検出されたメモリーアクセスエラーのリストが表示されます。
エラーをクリックすると、エラー時のスタックトレースが表示されます。
–g オプションを使用してコードをコンパイルした場合、関数をクリックするとスタックトレースの関数ごとのソースコードを表示できます。
「警告 (Warnings)」タブには、起こり得るアクセスエラーの警告メッセージのすべてが表示されます。警告をクリックすると、警告時のスタックトレースが表示されます。コードを –g オプションを使用してコンパイルした場合、関数をクリックすると、スタックトレースの関数ごとのソースコードを表示できます。
「メモリーリーク」タブには、下記にリストされているブロック数とともに、最上部にプログラムの実行終了時に割り当てられている残存ブロック総数が表示されます。
ブロックをクリックすると、ブロックのスタックトレースが表示されます。–g オプションを使用してコードをコンパイルした場合、関数をクリックすると、スタックトレースの関数ごとのソースコードを表示できます。
エラー、警告、およびメモリーリークのすべてのスタックトレースを表示するには、コントロールパネルの「スタックトレース」セクションの「すべて展開」をクリックします。関数のすべてのソースコードを表示するには、コントロールパネルの「ソースコード」セクションの「すべて展開」をクリックします。
エラー、警告、およびメモリーリークのすべてのスタックトレースまたはソースコードを非表示にするには、対応する「すべて折りたたむ (Collapse All)」をクリックします。
コントロールパネルの「エラーの表示」または「警告の表示」セクションは、対応するタブを選択したときに表示されます。デフォルトでは、検出されたエラーまたは警告のすべてのオプションがオンになっています。あるエラーまたは警告のタイプを非表示にするには、それを選択解除します。
エラーおよび警告の総数を一覧表示するレポートのサマリー、およびリークしたメモリー量がコントロールパネルの下方に表示されます。
discover レポートの ASCII (テキスト) 形式は、スクリプトで処理する場合や、Web ブラウザにアクセスできない場合に適しています。ASCII レポートの例を次に示します。
$ a.out ERROR 1 (UAW): writing to unallocated memory at address 0x50088 (4 bytes) at: main() + 0x2a0 <ui.c:20> 17: t = malloc(32); 18: printf("hello\n"); 19: for (int i=0; i<100;i++) 20:=> t[32] = 234; // UAW 21: printf("%d\n", t[2]); //UMR 22: foo(); 23: bar(); _start() + 0x108 ERROR 2 (UMR): accessing uninitialized data from address 0x50010 (4 bytes) at: main() + 0x16c <ui.c:21>$ 18: printf("hello\n"); 19: for (int i=0; i<100;i++) 20: t[32] = 234; // UAW 21:=> printf("%d\n", t[2]); //UMR 22: foo(); 23: bar(); 24: } _start() + 0x108 was allocated at (32 bytes): main() + 0x24 <ui.c:17> 14: x = (int*)malloc(size); // AZS warning 15: } 16: int main() { 17:=> t = malloc(32); 18: printf("hello\n"); 19: for (int i=0; i<100;i++) 20: t[32] = 234; // UAW _start() + 0x108 0 WARNING 1 (AZS): allocating zero size memory block at: foo() + 0xf4 <ui.c:14> 11: void foo() { 12: x = malloc(128); 13: free(x); 14:=> x = (int*)malloc(size); // AZS warning 15: } 16: int main() { 17: t = malloc(32); main() + 0x18c <ui.c:22> 19: for (int i=0; i<100;i++) 20: t[32] = 234; // UAW 21: printf("%d\n", t[2]); //UMR 22:=> foo(); 23: bar(); 24: } _start() + 0x108 ***************** Discover Memory Report ***************** 1 block at 1 location left allocated on heap with a total size of 128 bytes 1 block with total size of 128 bytes bar() + 0x24 <ui.c:9> 6: 7: void bar() { 8: int *y; 9:=> y = malloc(128); // Memory leak 10: } 11: void foo() { 12: x = malloc(128); main() + 0x194 <ui.c:23> 20: t[32] = 234; // UAW 21: printf("%d\n", t[2]); //UMR 22: foo(); 23:=> bar(); 24: } _start() + 0x108 ERROR 1: repeats 100 times DISCOVER SUMMARY: unique errors : 2 (101 total, 0 filtered) unique warnings : 1 (1 total, 0 filtered)
このレポートはエラーと警告メッセージ、およびそのサマリーで構成されます。
エラーメッセージには、ERROR という単語で始まり、3 文字のコード、ID 番号、およびエラーの説明 (この例では、writing to unallocated memory) が含まれています。その他の詳細には、アクセスされたメモリーアドレスと、読み取られた、または書き込まれたバイト数が含まれます。説明のあとには、プロセスライフサイクルでエラーの場所を自動補完するエラー時のスタックトレースが表示されます。
–g オプションを使用してプログラムをコンパイルすると、スタックトレースにソースファイル名と行番号が含まれます。ソースファイルにアクセス可能な場合、エラー付近のソースコードが出力されます。各フレームのターゲットソース行は、⇒記号によって示されます。
同じバイト数を持つ同じメモリーの場所の同じエラーの種類が繰り返される場合、スタックトレースを含む完全なメッセージが 1 度だけ出力されます。後続のエラーの出現が数えられ、次の例に表示されるように繰り返し数が、複数回発生する同一エラーごとにレポートの末尾に一覧表示されます。
ERROR 1: repeats 100 times
不正なメモリーアクセスのアドレスがヒープ上にある場合、対応するヒープブロックに関する情報がスタックトレース後に出力されます。その情報には、ブロック開始アドレスとサイズ、およびブロックが割り当てられた時点のスタックトレースが含まれます。ブロックが解放された場合は、解放ポイントのスタックトレースもレポートに含まれます。
警告メッセージは、WARNING という単語で始まる点を除き、エラーメッセージと同じ形式で表示されます。これらのメッセージは、一般にアプリケーションの機能に影響を及ぼさない状態に対する警告ですが、問題を改善するために使用できる有益な情報を提供します。たとえば、0 サイズのメモリーを割り当てることは有害ではありませんが、頻繁すぎると、パフォーマンスを低下させる可能性があります。
メモリーリークレポートには、ヒープ上に割り当てられているがプログラムの終了時にリリースされないメモリーブロックに関する情報が含まれます。メモリーリークレポートの例を次に示します。
$ DISCOVER_MEMORY_LEAKS=1 ./a.out ... ***************** Discover Memory Report ***************** 2 blocks left allocated on heap with total size of 44 bytes block at 0x50008 (40 bytes long) was allocated at: malloc() + 0x168 [libdiscover.so:0xea54] f() + 0x1c [a.out:0x3001c] <discover_example.c:9>: 8: { 9:=> int *a = (int *)malloc( n * sizeof(int) ); 10: int i, j, k; main() + 0x1c [a.out:0x304a8] <discover_example.c:33>: 32: /* Print first N=10 Fibonacci numbers */ 33:=> a = f(N); 34: printf("First %d Fibonacci numbers:\n", N); _start() + 0x5c [a.out:0x105a8] ...
ヘッダーに続く最初の行は、ヒープ上に割り当てられて残されているヒープブロック数とその合計サイズを要約しています。レポートされるサイズは、開発者の見解であり、すなわちメモリーアロケータのブックキーピングのオーバーヘッドは含まれません。
メモリーリークのサマリーのあとに、割り当てポイントのスタックトレースを持つ未解放ヒープブロックごとの詳細情報が提供されます。スタックトレースレポートは、エラーおよび警告メッセージに対して説明されるレポートと同様です。
discover レポートの最後には、全体的なサマリーが出力されます。かっこ付きの一意の警告およびエラー数、繰り返しを含むエラーおよび警告の総数が報告されます。例:
DISCOVER SUMMARY: unique errors : 3 (3 total) unique warnings : 1 (5 total)