[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[freewnn:00840] malloc()
- To: freewnn@tomo.gr.jp
- Subject: [freewnn:00840] malloc()
- From: Hiroo Ono <hiroo@XXXX>
- Date: Wed, 01 May 2002 08:55:32 +0900
- In-Reply-To: <020331031022.M0128682@ikoma.cc.osaka-kyoiku.ac.jp>
- Reply-To: freewnn@tomo.gr.jp
- User-Agent: Wanderlust/2.8.1 (Something) SEMI/1.14.3 (Ushinoya) FLIM/1.14.3(Unebigoryōmae) APEL/10.3 Emacs/21.2 (i386--freebsd)MULE/5.0 (SAKAKI)
小野寛生です
期末期初でばたばたしていたこともあり、こっちは全然動いていませんでした。
At Sun, 31 Mar 2002 03:10:22 JST,
Tomoki AONO wrote:
> #検証するひまがありません…。それ以前に何を検証するのか、
> #というのもありますが。
ここしばらく変更をかけているのは、error.c patch 以外は動作を変えないは
ずのものなので、
・compile が通るか。
・jserver を始めとするプログラムが起動するか。
・jserver のエラー/警告がきちんと出力されるか。
くらいを見れば十分だと思っています。
あとは、各言語で変換が出来るかどうかでしょう。
> >> ・malloc & free
> >> これは、GNU coding style に書いてあることにのっとって、
> (略)
> 定式のようなものがあるのならそれに従う方がよいでしょう。
GNU コーディング規約
http://www.sra.co.jp/wingnut/standards-j_toc.html#System%20Functions
では、
・ システム関数の宣言を行わなければならない場合は,引数の型を指定しないでくださ
い. 標準 C のプロトタイプ宣言ではなくて,古い C スタイルの宣言を使ってくださ
い.関数についてそれ以上何かを指定すると,もっと衝突が発生します.
・ 特に,無条件に malloc や realloc を宣言するのはやめてください.
大部分の GNU プログラムでは,これらの関数は一度だけ, xmalloc とxrealloc とい
う名前の関数で使うようになっています. これらの関数は,それぞれ, malloc と
realloc を呼び出して, 結果のチェックを行っています.
xmalloc と xrealloc は,自分のプログラムの中で定義することになるので,衝突の
恐れなく他のファイルで宣言を行うことができます.
ほとんどのシステムでは, int はポインタと同じ大きさです. つまり, malloc と
realloc は宣言無しでも正しく動作します. int とポインタの大きさが同じでない
例外的なシステム(大部分は 64 ビットマシン)のためには, #ifdef 等でかこって
malloc と realloc を宣言するか, 宣言をそういうシステムに固有のコンフィギュ
レーションファイルに書くことにすれば良いでしょう.
とあります。
% ansidecl.h では他のやりかたをしていますが
autoconf を使って、
#if STDC_HEADERS
# include <stdlib.h>
#else
# if HAVE_MALLOC_H
# include <malloc.h>
# endif
#endif /* STDC_HEADERS */
とすれば、よほど昔のシステムでないかぎり、システムのヘッダで malloc の
プロトタイプ宣言が行なわれるはずです。行なわれないのがあっても、
ほとんどのシステムでは, int はポインタと同じ大きさです. つまり, malloc と
realloc は宣言無しでも正しく動作します.
にあてはまると思います。
> >> で、wnn_malloc.h とか MALLOC.c とか削除出来るかな…と思っています。
> MALLOC.cでしているのはプログラムミスを防ぐためのチェックが
> 入っているだけだと思うので、無理して外す必要もないのではな
> いかと思います。wnn_malloc.h内のプロトタイプ宣言での条件分
> 岐は削除するべきですが。
このあたり、Wnn/jserver でしか使っていないようですが、
MALLOC.c は使われていない。
malloc.c では、malloc0()、realloc0()、free0() の 3関数を定義。
wnn_malloc.h では、
malloc()、realloc()、free() を上記3関数に define するのと
併せて prototype 宣言を行なう。
となっています。
malloc0, realloc0 の定義をこのあと引用しますが、
malloc0 は、
(1) 指定された size が NULL だったら、8bytes 確保するように切り上げ。
(結果として size=0 でも同じでしょう)。
(2) 指定された size を 8bytes 単位に切り上げ。
(3) 領域は calloc で確保 (i.e. 必ず初期化)。
realloc0 は、
(4) 渡された pointer の値が が NULL だったら、malloc() で確保。
(2) 指定された size を 8bytes 単位に切り上げ。
という動きです。
65 malloc0 (size)
66 int size;
68 {
69 if (size == NULL)
70 {
71 size = 1;
72 }
73 size = (size + 7) & 0xfffffff8;
74 return (calloc (size, 1));
75 }
100 realloc0 (pter, size)
101 char *pter;
102 int size;
104 {
105 if (size == NULL)
106 {
107 size = 1;
108 }
109 size = (size + 7) & 0xfffffff8;
110 if (pter == NULL)
111 return (malloc (size));
112 return (realloc (pter, size));
113 }
(1) は、malloc に size=0 を指定した場合に、実装によって振舞がことなる
のを嫌ってなのかもしれませんが、それなら、むしろ呼ぶ前にチェックすべき
かと思います。
(2) については、このような操作が必要だとしても、それはシステムの
malloc() の実装に期待してよいことではないかと思います。
また、このやりかたの問題として、sizeof(size_t)==4 であることを仮定した
コードになっていることがあります。
(実用上は、そこまで大きなメモリを malloc/realloc で要求することがなく、
問題は起きないのではないかと_思って_はいますが…)。
(3) については、初期化が必要なら、explicit に calloc() を呼ぶべきと思っ
ています。これについては、
・あえてこうした理由があるのか。
・単なる malloc にして、必要な初期化が洩れることになる部分はあるか。
という点での調査が必要とは思いますが。
(4) は、realloc() に期待される動作であって、わざわざこのように wrap す
る意味はないと思います。
free0 については、
83 free0 (pter)
84 char *pter;
86 {
87 if (pter == NULL)
88 return;
89 free (pter);
90 return;
91 }
となっていますが、free() は NULL を渡しても正常に動く (何もしない) はず
なので、無意味だと思います。
以上から、
(1) に関連して、
Wnn/jutil/wddel.c にある
rb.buf = (char *) malloc ((unsigned) (rb.size = 0));
を
rb.buf = NULL;
rb.size = 0;
に修正するというような変更を行なう。
(3) に挙げた調査&必要な変更を行なう。
(といっても、元木さんがだいぶ前に一通り調べて下さっているようですが)。
とやって行くことにすれば、malloc.c、MALLOC.c、wnn_malloc.h は捨ててしまって
よいと思います。