さて、char buffer[100] とかを局所変数として作ると、どこにできるのか? 実は、配列も普通の局所変数と同じで stack frame 上に作られます。 たとえば、以下のプログラム(ソース)の中では、
一方で、当然ですが、ポインタ型の局所変数についても ポインタ用の領域が frame 上に確保されます。 ですから、このプログラムの実行はだいたいこんな感じになります。
メソッドの引数のところを char * a と書いても char a[] と書いても同じ意味にとられます(C の統一間のないところ)。 引数のところに配列の型を書いても、ポインタの意味で解釈されちゃうよって思っておくとすっきりするでしょう。
char * copyString(char * org) { /* org から buffer に値をコピーして、buffer を返す(イケナイ事) */ char buffer[1000]; strcpy(buffer, org); return buffer; } int main(int argc, char** argv) { char * first_one; .... char sampleA[] = "AAAAAA"; .... first_one = copyString(sampleA);さて、なにが問題かというと、 buffer のポインタを呼び出し側に向けて漏らしています。 つまり、局所変数は関数呼び出しが終わるとなくなり、そのうち、別の関数呼び出しで同じ領域が使われることになります。 ですから、first_oneは、指している「相手が(確実には)いない宙ぶらりんなポインタ」になってしまいます。 実際、プログラムを実行すると、first_one の中身は、別の関数呼び出しが実行される度に変わってしまうことがあります。 こんな感じ。 実際に、debugger などでも挙動を確かめてみましょう。
実は、コンパイルの段階から、コンパイラは「ヤバイ、ヤバイ」って騒いでくれます。 皆さんは、コンパイラの助言に耳を傾けてください。
kamada@shusaku%gcc readlineB.c readlineB.c: In function `copyString': readlineB.c:6: warning: function returns address of local variable
実は、もうひとつヤバイ事があるんですが、それは余談で。
2002.10.14/ Tomio KAMADA: kamada@cs.kobe-u.ac.jp