本節の最初で述べた本来の作業に戻り、「out of storage」のエラーメッセージの原因となっている場所を確定します。cscope が起動され、相互参照表が作成されました。画面には、cscope の作業メニューが表示されます。
cscope の作業メニュー
% cscope cscope Press the ? key for help Find this C symbol: Find this global definition: Find functions called by this function: Find functions calling this function: Find this text string: Change this text string: Find this egrep pattern: Find this file: Find files #including this file: |
Return キーを押すと、カーソルが下に移動し (画面の一番下まで移動すると、先頭に戻る)、^p (Ctrl+p キー) を押すと、上に移動します。また、上矢印 (ua) と下矢印 (da) キーも使用できます。次の単一キーコマンドを使用すれば、メニュー操作とそのほかの作業が行えます。
表 8–1 cscope メニュー操作コマンド
Tab |
次の入力フィールドへ移動する |
Return |
次の入力フィールドへ移動する |
^n |
次の入力フィールドへ移動する |
^p |
前の入力フィールドへ移動する |
^y |
最後に入力したテキストを検索する |
^b |
逆方向にパターンを検索する |
^f |
順方向にパターンを検索する |
^c |
検索時に大文字と小文字を区別するか否かのトグルスイッチ (大文字と小文字を区別しない場合、たとえば FILE 文字列は file と File の両方と一致)。 |
^r |
相互参照表を再作成する |
! |
対話型シェルを起動する (^d で cscope に復帰) |
^l |
画面を描き直す |
… |
コマンドのリストを表示する |
^d |
cscope を終了する |
検索文字列の最初の文字が前述のいずれかのコマンドと一致する場合は、検索文字列の前にバックスラッシュ (\) を加えてコマンドと区別します。
たとえば、カーソルを 5 番目のメニュー項目「Find this text string」に移動して文字列「out of storage」を入力し、Return キーを押します。
cscope 関数: 文字列検索の要求
$ cscope cscope Press the ? key for help Find this C symbol Find this global definition Find functions called by this function Find functions calling this function Find this text string: out of storage Change this text string Find this egrep pattern Find this file Find files #including this file |
6 番目の「Change this text string」項目以外のメニュー項目についても同じ手順に従ってください。6 番目の項目はほかの項目よりも多少複雑なので手順が異なります。文字列の変更方法については、「8.2.8 例」を参照してください。
cscope は指定された文字列を検索し、それを含む行を見つけ出して次のように検索結果を表示します。
cscope 関数: 文字列を含む cscope 行のリスト表示
Text string: out of storage File Line 1 alloc.c 63 (void) fprintf(stderr, "\n%s: out of storage\n", argv0); Find this C symbol: Find this global definition: Find functions called by this function: Find functions calling this function: Find this text string: Change this text string: Find this egrep pattern: Find this file: Find files #including this file: |
検索結果が正常に表示されたら、次の操作を選択します。行を変更したり、またはその行の前後をエディタで調べることができます。あるいは、cscope の検索結果のリストが一画面に収まらない場合は、リストの次の部分を見ることもできます。cscope が指定した文字列を検索したあとに使用可能なコマンドを次に示します。
表 8–2 最初の検索後に使用するコマンド
1 -9 |
この行を含むファイルを編集する(入力した番号は cscope が表示したリストの行番号に対応する) |
スペース |
次画面のリストを表示する |
+ |
次画面のリストを表示する |
^v |
次画面のリストを表示する |
… |
前画面のリストを表示する |
^e |
表示されたファイル順に編集する |
> |
表示されているリストをファイルへ追加する |
| |
全行をパイプでシェルコマンドに渡す |
ここでも、検索文字列の最初の文字が前述のいずれかのコマンドと一致する場合は、検索文字列の前にバックスラッシュ (\) を加えてコマンドと区別します。
次に、新しく検索した行の前後を調べます。「1」 (リスト内の行番号) を入力してください。エディタが起動され、alloc.c ファイルが読み込まれます。カーソルは、 alloc.c の 63 行目の先頭に移動します。
cscope 関数: コード行の検査
{ return(alloctest(realloc(p, (unsigned) size))); } /* メモリーの割り当て失敗を検査する */ static char * alloctest(p) char *p; { if (p == NULL) { (void) fprintf(stderr, "\n%s: out of storage\n", argv0); exit(1); } return(p); } ~ ~ ~ ~ ~ ~ ~ "alloc.c" 67 lines, 1283 characters |
変数 p が NULL のときに、エラーメッセージが出力されることがわかります。alloctest() に渡される引数がなぜ NULL になったのかを調べるには、まず alloctest() を呼び出している関数を確定する必要があります。
通常の終了方法でエディタを終了し、作業メニューに戻ります。ここで、4 番目の項目「Find functions calling this function」のあとに alloctest と入力します。
cscope 関数: alloctest() を呼び出す関数のリストの要求
Text string: out of storage File Line 1 alloc.c 63(void)fprintf(stderr,"\n%s: out of storage\n",argv0); Find this C symbol: Find this global definition: Find functions called by this function: Find functions calling this function: alloctest Find this text string: Change this text string: Find this egrep pattern: Find this file: Find files #including this file: |
cscope は検索を実行し、次の 3 つの関数のリストを表示します。
cscope 関数: alloctest() を呼び出す Listing 関数
Functions calling this function: alloctest File Function Line 1 alloc.c mymalloc 33 return(alloctest(malloc((unsigned) size))); 2 alloc.c mycalloc 43 return(alloctest(calloc((unsigned) nelem, (unsigned) size))); 3 alloc.c myrealloc 53 return(alloctest(realloc(p, (unsigned) size))); Find this C symbol: Find this global definition: Find functions called by this function: Find functions calling this function: Find this text string: Change this text string: Find this egrep pattern: Find this file: Find files #including this file: |
今度は、mymalloc() を呼び出す関数を調べます。cscope は、次のような 10 個の関数を見つけ出します。そのうち 9 個を画面に表示し、残りの 1 個を見るにはスペースバーを押すように指示しています。
cscope 関数: mymalloc() を呼び出す Listing 関数
Functions calling this function: mymalloc File Function Line 1 alloc.c stralloc 24 return(strcpy(mymalloc (strlen(s) + 1), s)); 2 crossref.c crossref 47 symbol = (struct symbol *)mymalloc (msymbols * sizeof(struct symbol)); 3 dir.c makevpsrcdirs 63 srcdirs = (char **) mymalloc (nsrcdirs * sizeof(char*)); 4 dir.c addincdir 167 incdirs = (char **)mymalloc (sizeof(char *)); 5 dir.c addincdir 168 incnames = (char **) mymalloc(sizeof(char *)); 6 dir.c addsrcfile 439 p = (struct listitem *) mymalloc (sizeof(struct listitem)); 7 display.c dispinit 87 displine = (int *) mymalloc (mdisprefs * sizeof(int)); 8 history.c addcmd 19 h = (struct cmd *) mymalloc (sizeof(struct cmd)); 9 main.c main 212 s = mymalloc((unsigned ) (strlen(reffile) +strlen(home) + 2)); * 9 more lines- press the space bar to display more * Find this C symbol: Find this global definition: Find functions called by this function: Find functions calling this function: Find this text string: Change this text string: Find this egrep pattern: Find this file: Find files #including this file: |
「out of storage」のエラーメッセージはプログラムの開始直後に出力されるので、関数 dispinit() (表示の初期化) 内で問題が発生していることが推測できます。
dispinit() はリストの 7 番目の関数なので、これを参照するには「7」と入力します。
cscope 関数: dispinit() をエディタで参照
void dispinit() { /* 表示される参照行数の最大を計算する */ lastdispline = FLDLINE- 4; mdisprefs = lastdispline- REFLINE + 1; if (mdisprefs > 9) { mdisprefs = 9; } /* 表示される行の配列を割り当てる */ displine = (int *) mymalloc(mdisprefs * sizeof(int)); } ^L/* 参照ページを表示する */ void display() { char file[PATHLEN + 1]; /* ファイル名 */ char function[PATLEN + 1];/* 関数行 */ char linenum[NUMLEN + 1]; /* 行番号 */ int screenline; /* 画面行番号 */ int width; /* ソース行表示幅 */ register int i, j; "display.c" 622 lines, 14326 characters |
mymalloc() が失敗したのは、非常に大きな数または負数を引数にして呼び出されたためです。FLDLINE と REFLINE が取り得る値を調べてみると、mdisprefs の値が負になる場合があることがわかります。この場合、mymalloc() は負数を引数にして呼び出されます。