本節の最初で述べた本来の作業に戻り、out of storage のエラーメッセージの原因となっている場所を確定します。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 キー) を押すと上に移動します。また、上矢印と下矢印キーも使用できます。以下の単一キーコマンドを使用すれば、メニュー操作とその他の作業が行えます。
表 4-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 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 番目の項目は他の項目よりも多少複雑なので手順が異なります。文字列の変更方法については 「cscope の使用例」を参照してください。
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 が指定した文字列を検索した後に使用可能なコマンドを以下に示します。
表 4-2 最初の検索後に使用するコマンド
1 - 9 |
この行を含むファイルを編集する (入力した番号は cscope が表示したリストの行番号に対応する) |
スペース |
次画面のリストを表示する |
+ |
次画面のリストを表示する |
^v |
次画面のリストを表示する |
- |
前画面のリストを表示する |
^e |
表示されたファイル順に編集する |
> |
表示されているリストをファイルへ追加する |
| |
全行をパイプでシェルコマンドに渡す |
ここでも、検索文字列の最初の文字が上記のいずれかのコマンドと一致する場合は、検索文字列の前にバックスラッシュ (¥) を加えてコマンドと区別します。
次に、新しく検索した行の前後を調べます。「1」(リスト内の行番号) を入力してください。エディタが起動され、alloc.c ファイルが読み込まれます。カーソルは、alloc.c の 63 行目の先頭に移動します。
{ 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 makevpsrcdirs63 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() は負数を引数にして呼び出されます。