April 16, 2007mallocは関数の中ですべきか[Computer]
C言語の行列ライブラリを訳あって書いていました。その中でふと思ったのが、今回の記事の表題にあるとおりで、結果を引数として指定されたポインタを通じて返す関数では、関数内でmallocするべきか否かという宗教じみた話です。 このことは特に、関数が場合によって異なるサイズの配列を返す場合で問題になると思います。 void caller_func(){
char input; char *outputs; int number_of_outputs; /* input に対して何か処理 */ callee_func(&input, &outputs, &number_of_outputs); free(outputs); } void callee_func(char *input, char *outputs[], int *number_of_output){ mallocを関数の中で使わないとすれば、外で大きめのメモリを確保して渡すことになります。 void caller_func(){
char input; char outputs[256]; int number_of_outputs; /* input に対して何か処理 */ callee_func(&input, outputs, &number_of_outputs); } void callee_func(char *input, char outputs[], int *number_of_outputs){ どちらがスマートでしょうか。入力と出力の関係が常に固定、あるいはそこまでいかなくとも予想が付くのなら、関数の外で大きめのバッファを用意するのがメモリリークの心配もなく良いと思います。しかし、文字列処理など一体最大の大きさがどの程度になるかわからないという場合は関数内でmallocという方法にも一利あると思います。 そこで師匠であるA氏に相談したところ、Cライブラリに沿うようにすれば、ということでした。これはmallocするもしないもどちらにも対応するようにする方法で、引数を見てNULLが入っていたらmallocでメモリを割り当てて、そうでない場合はmallocしないでバッファが外で確保されているとして処理する方法です。例題でいうとmallocを使う版において*outputsでスイッチにすることに相当し、コードで書くと次のようになります。 void callee_func(char *input, char *outputs[], int *number_of_output){
*number_of_outputs = (int)(random() * 100); if(!(*output)){*outputs = (char *)malloc(sizeof(char) * number_of_outputs);} /* (*outputs)[i] に対する何か処理 */ } なるほど、これなら使い分けられます。 コメント
私は関数が返す値を決して関数内でmalloc()しません。なぜなら、受け取った値をfree()すべきかどうか、必ず間違うからです。他の人は知りませんが、私は間違います。賭けてもいい。 >酔漢さん コメントする
|
スポンサード リンク
|