[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[freewnn:00840] malloc()



小野寛生です
期末期初でばたばたしていたこともあり、こっちは全然動いていませんでした。

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 は捨ててしまって
よいと思います。


http://www.freewnn.org/ FreeWnn Project