C言語の本をにはたいてい
mallocしたメモリーをもう使わないなら放っておけば
終了時に自動的に解放されるので明示的にfreeしなくても良い
と書いてあるのですが、先日ある雑誌を見ると
明示的にfreeしないとメモリーリークになる
と書かれていました。どちらが正しいのでしょうか。
Arita
それは言語仕様の問題ではなくてOSの問題です。まとも
なOSなら、malloc()から呼ばれたシステムコールで確保
されたメモリーはプログラムの終了時には解放されるは
ずです。なぜかというと、OSをそのように作っておかな
いといろいろな問題が起きて困るからです。したがって、
陽にfree()する必要はない、というのが一般解です。
「ある雑誌」に書かれていたのは特定のOSのバグについ
ての記述ではないでしょうか?
--
太田純(Junn Ohta) (株)リコー 販事本S計画C NWS計画室S開G
oh...@src.ricoh.co.jp/JCF0...@nifty.ne.jp
bar...@geocities.co.jpさん:
> mallocで確保したメモリーをfreeしないといけないかどうかについて
> 質問させてください。
freeしないといけません。
> C言語の本をにはたいていmallocしたメモリーをもう使わないなら放っ
> ておけば終了時に自動的に解放されるので明示的にfreeしなくても良
> いと書いてあるのですが、
もし良ければ、それらの本の書名を教えて頂けませんか。 久野
P.S. 終了時に解放されるかどうかはOSの機能次第ですが、長時間動き
続けるソフトを書くときそんなことをしたらえらいことになるの
で、必ず解放する習慣をつけるべきです。
> それは言語仕様の問題ではなくてOSの問題です。まとも
> なOSなら、malloc()から呼ばれたシステムコールで確保
> されたメモリーはプログラムの終了時には解放されるは
> ずです。なぜかというと、OSをそのように作っておかな
> いといろいろな問題が起きて困るからです。したがって、
> 陽にfree()する必要はない、というのが一般解です。
>
今やってみたところNTとSolarisはfreeしなくても良いみたいですね。
DOS/Windows95ではどうなんでしょうか。
ku...@gssm.otsuka.tsukuba.ac.jpさん
>もし良ければ、それらの本の書名を教えて頂けませんか。
>久野
三田さんの実習C言語(実践C言語だったかも)
に例付きで書いてあります。一応DOSを念頭におきつつ
すべてのプラットホームに対して有効という触れ込みの本なんですが。
VCの本も含めて片っ端から立ち読みしてみたところ
その他多くの本に
freeせずに放っておいて良い
と書いてあるので見つけ出すのは難しくないと思います。
Arita
Arita <bar...@geocities.co.jp> wrote in message news:38AB90...@geocities.co.jp...
> oh...@src.ricoh.co.jpさん
>
> > それは言語仕様の問題ではなくてOSの問題です。まとも
> > なOSなら、malloc()から呼ばれたシステムコールで確保
> > されたメモリーはプログラムの終了時には解放されるは
> > ずです。なぜかというと、OSをそのように作っておかな
> > いといろいろな問題が起きて困るからです。したがって、
> > 陽にfree()する必要はない、というのが一般解です。
> >
>
> 今やってみたところNTとSolarisはfreeしなくても良いみたいですね。
> DOS/Windows95ではどうなんでしょうか。
OS の問題でもありますが、MS-DOS とかまで視野に入れると
C runtime library とかの問題でもあります。
で、MS-DOS の場合では、MS-C とかを使っていたなら、通常
の終了手順で終了した場合なら(プログラムが落ちたとかじゃな
くて)、メモリーは解放されるはず。あの OS の場合は、OS がメ
モリーの管理って言って良いかってのは取り敢えず脇に置く。(^^;
Windows95 の場合も似たようなもので、通常の手順で終了した
なら、本来なら解放されるはずですが、何故かそうならない時も
あるような。メモリー以外のリソース含めて。
> ku...@gssm.otsuka.tsukuba.ac.jpさん
>
> >もし良ければ、それらの本の書名を教えて頂けませんか。
> >久野
>
> 三田さんの実習C言語(実践C言語だったかも)
> に例付きで書いてあります。一応DOSを念頭におきつつ
> すべてのプラットホームに対して有効という触れ込みの本なんですが。
> VCの本も含めて片っ端から立ち読みしてみたところ
> その他多くの本に
> freeせずに放っておいて良い
> と書いてあるので見つけ出すのは難しくないと思います。
これも状況依存でしょう。
OS や CRT がちゃんと後処理してくれるようなシステムで、その
プログラムのプロセスの寿命も短く、メモリー資源もほとんど使わ
ないようなものの場合、明示的に解放しなくても「実用上多くは」
問題ないってことで、久野さんが指摘しているような、プログラム
のプロセスとしての寿命が長く、メモリー資源も使い捨てをし、い
らなくなったメモリーを解放しないと時間とともに消費量が増大す
るようなプログラムの場合は、いらなくなったらちゃんと明示的に
解放してやらないととんでもないことになる。
まあ、後者のことを考えたら、プログラマの良心として、前者の
場合でもちゃんと管理するようにしている方が、C言語プログラ
マの態度として、canonical ですね。
--
Narita Takaoki @A.I.SOFT,INC.
スタンスの違いといえばそれまでですが、
> P.S. 終了時に解放されるかどうかはOSの機能次第ですが、長時間動き
> 続けるソフトを書くときそんなことをしたらえらいことになるの
> で、必ず解放する習慣をつけるべきです。
そういう習慣を身につけることの正しさはともかくとし
て、何でも安全側に振っておけば問題ないとしてシステ
ムを理解しようとしない、あるいは理解せずにすませて
しまう姿勢にも問題があるよなあ、と私はつねづね思っ
ているのでした。
で、こういう質問にはやっぱり「システムがきちんとめ
んどうはみてくれるけど、だからってさぼっちゃだめだ
よ」と答えるべきなんでしょうか...。
In article <UEHARA.00F...@maia0.ec.ntts.co.jp>
ueh...@po.ntts.co.jp (UEHARA, Junji) writes:
|int main(int argc, char** argv) {
| int n = atoi(argv[1]);
| int* data = (int*)malloc(n * sizeof(int));
~
|}
ここに
free(data);
を追加しといてください(^^;。
# Javaを書きすぎた..。
--
§NTTS○FT 技術開発部エレクトロニックコマース技術センター 上原 潤二 §
PGP Key fingerprint = B7 C0 CB 1F 1C 88 69 2A 25 36 8A EE 93 A3 61 72
>そういう習慣を身につけることの正しさはともかくとし
>て、何でも安全側に振っておけば問題ないとしてシステ
>ムを理解しようとしない、あるいは理解せずにすませて
>しまう姿勢にも問題があるよなあ、と私はつねづね思っ
>ているのでした。
でも malloc は free する「仕様」の関数です。
ある特定の OS のメモリ関連のコールの仕様と
勝手な判断で一緒にする姿勢に問題があるのでしょう。
こんな基本的なことが、*本気で* わからない人材を
育ててしまうことこそ、「free しなくてよい」とアドバイスして
しまうことの問題の本質だと思います。
oh...@src.ricoh.co.jpさん:
> そういう習慣を身につけることの正しさはともかくとして、何でも安
> 全側に振っておけば問題ないとしてシステムを理解しようとしない、
> あるいは理解せずにすませてしまう姿勢にも問題があるよなあ、と私
> はつねづね思っているのでした。
そうかも知れません。私、Unixであれば大丈夫なのは知っていますが
DOSなんかだと怪しそうなんで絶対安全サイドで作っちゃうと思うな。
いい加減な奴ですいません。
でもDOSで動かすプログラムなんてまず絶対作らないか。 久野
In article <88gq1e$soq$1...@news01be.so-net.ne.jp> ,
"Yoshiki Kataoka" <kat...@ka2.so-net.ne.jp> writes
>でも malloc は free する「仕様」の関数です。
そうとは思わないな。多量に malloc した後、ランダムな順序で free
すると極めて遅くなる malloc はいくつかあります。このような場
合は、free しないで抜けるほうが正しい。
C++ の場合は、オブジェクトの後始末があるので、destructを強制
されますが、おかげで、殺してもなかなかしなないアプリケーショ
ンがたくさんあるでしょう? それが当り前だとおもってはいけなくて、
ちゃんと早く終れるものは早く終っておくほうがいいと思います。
>ある特定の OS のメモリ関連のコールの仕様と
>勝手な判断で一緒にする姿勢に問題があるのでしょう。
exit 時に、どの領域のメモリが残るかどうかは、malloc とは
独立の問題です。そのあたりをごっちゃにすべきではないです。
>こんな基本的なことが、*本気で* わからない人材を
>育ててしまうことこそ、「free しなくてよい」とアドバイスして
>しまうことの問題の本質だと思います。
僕は、exit() するなら、close しなくてもいいし、free しなくても
良いって教えます。exit()がcloseするのは仕様ですし、exit()で
プロセスのメモリ領域が解放されるのも仕様ですよね。
ようは、ちゃんと理解していればいいのでしょう?
---
Shinji KONO @ Information Engineering, University of the Ryukyus
河野真治 @ 琉球大学工学部情報工学科
In article <38AB90...@geocities.co.jp>
Arita <bar...@geocities.co.jp> writes:
| > それは言語仕様の問題ではなくてOSの問題です。まとも
| > なOSなら、malloc()から呼ばれたシステムコールで確保
| > されたメモリーはプログラムの終了時には解放されるは
| > ずです。なぜかというと、OSをそのように作っておかな
| > いといろいろな問題が起きて困るからです。したがって、
| > 陽にfree()する必要はない、というのが一般解です。
|
| 今やってみたところNTとSolarisはfreeしなくても良いみたいですね。
「しなくて良い」というのがちょびっと引っかかりますね。
「必要はない」≠「しなくて良い」
です。
・積算して使用するメモリが少量であり、
・あるいは実行が短時間であることが確定しているなどの理由で
・メモリを解放しないことでシステムに負荷をかけないこと、
・そしてこのことがそのプログラムのユーザが使う可能性の
あるすべての環境において真であり、今後永劫に真であると見込まれ
・さらにそのプログラム断片を再利用して、全く別のプログラムに
組み込んだりする可能性が無いこと
などの条件が成り立つならたぶん「しなくて良い」でしょうが、
本当にそうなのか、よくよく考えてみてください。
でも結局、こういうことは、実は痛い目にあってこそ良く分かります。
Windowsのサービスを作ったとして、パフォーマンスモニタで見てもすぐには
良く分からないほどメモリ使用量がじわじわと上がっていき、1週間後には使
い物にならないほどNTが重くなるような、そんな持病を持った数万~十数万
行のプログラムを目前に立ち尽くしたときを想像してみてください。「自動リ
ブート」なんかで逃げちゃ駄目だ、逃げちゃ駄目だ、と自分に言い聞かせた、
そんなことも今では良い思い出です。
あと、サービスじゃなくても、ノートPCとか、Windows 2000とか、サスペン
ド・レジュームできる環境が普及してきて、半年とか1年とかの期間プログラ
ムが走る、ってのがそれほど珍しいことじゃなくなってくる、ってことも考え
といても良いでしょう。
これは正しくないのではないですか?
malloc()がシステムからメモリーをもらってくる関数で
あることは正しいのですが、free()はその逆をする関数
ではないのです。free()はむしろ、そのあとでmalloc()
を行ったときに再確保されるメモリーを用意する関数と
とらえたほうがいいでしょう。
つまりmalloc()とfree()は対称で対等な関係にあるわけ
ではないということです。
malloc()したものは無条件にfree()すべきだと教えるこ
とは、その非対称性に気づくチャンスを奪うことにもつ
ながりますよね。
# もちろん、malloc()で使い終わったメモリーはその段
# 階でfree()するのがよい習慣だという点については何
# の異議もありません。
元記事の方は、そのようなmalloc()の使いかたをしてい
るときに使い終わったメモリーをfree()しなくてよいか
とお尋ねなのではないでしょう。
むしろ、そのようなプログラムが長々と稼働したあとで
仕事を終えて終了する直前に、それまで確保していたこ
まごまとしたメモリーをすべての個別に解放することが
本質的に必要なのかをお尋ねなのだと思います。
それらはべつの問題ですよね。
これらを混同して安全側に振っても不利益がそれほどあ
るとは思えませんが、問題が異なることは理解しておい
たほうがいい、というのが私の考えです。
oh...@src.ricoh.co.jpさん:
> malloc()がシステムからメモリーをもらってくる関数であることは正
> しいのですが、free()はその逆をする関数ではないのです。free()は
> むしろ、そのあとでmalloc() を行ったときに再確保されるメモリー
> を用意する関数ととらえたほうがいいでしょう。
たとえfree()が「何もしない」関数だとしても、free()を呼びたい ^_^;
そうか、河野さんが言っているような場合は何もしないfree()を条件
付きコンパイルで突っ込めばいいのか。
> malloc()したものは無条件にfree()すべきだと教えることは、その非
> 対称性に気づくチャンスを奪うことにもつながりますよね。
別にmalloc()とfree()とは何かということを普通に教えればいいよう
な気がするんですけど。もっといいのは自前でmalloc()とfree()を書か
せることだったりして。
ところで、控え目GCを入れちゃってfree()は呼ばないことにする、と
いうのならそれもいいと思ってます。
どうも「保守的GC」という訳語は嫌いで… 久野
「もういらない」ということをシステムに伝える関数と
してfree()を呼ぶのはよいことだと私も思います。そう
伝えてシステムが何をしてくれるかについては過剰な期
待をしないという前提で、ですが...。:-)
> 別にmalloc()とfree()とは何かということを普通に教えればいいよう
> な気がするんですけど。もっといいのは自前でmalloc()とfree()を書か
> せることだったりして。
ですね。ある意味「プログラム作法」なお話かな。
> ところで、控え目GCを入れちゃってfree()は呼ばないことにする、と
> いうのならそれもいいと思ってます。
mark&releaseの昔に逆戻り、でしょうか。:-)
私自身はアプリケーションがどんなメモリーの使いかた
をするのかという状況判断を抜きにして一律にmalloc()
とfree()を使うことに、どちらかといえば反対です。
自分でメモリープールを作って上限の管理とか使用状況
の監視をしたほうがいいことはよくありますよね。
In article <88h6bs$v1$1...@ns.src.ricoh.co.jp> ,
oh...@src.ricoh.co.jp (Junn Ohta) writes
>私自身はアプリケーションがどんなメモリーの使いかた
>をするのかという状況判断を抜きにして一律にmalloc()
>とfree()を使うことに、どちらかといえば反対です。
僕もそう思います。fork()して、ひたすら malloc() しまくり exit()
というのは、Unix では、割と効率的なプログラミングです。
Effective C++ でも、自前のnew()を作ることは推奨していますね。
C++ で、destructor が必ず呼ばれてしまうのは、僕は、ある意味
で失敗だと思います。必要もないのに呼ぶのは変だし、効率を悪く
していることは確かです。
>自分でメモリープールを作って上限の管理とか使用状況
>の監視をしたほうがいいことはよくありますよね。
それもありますね。
>ですね。ある意味「プログラム作法」なお話かな。
malloc(),free() を必ず組で呼べば安全だってことにはならないと
思います。free() し忘れるってのが良くあることなのは認めるけ
ど、どちらかといえば、free()したのに、また使ってしまったとか
の方が危ないわけですよね。free()しなければ、そういうことには
なりません。
GC や、exit() の方がはるかに安全なことは確かだと思う。人の
感に頼って free() するのって、そんなに安全なことじゃない
と思いますね。alloca() とかの方がまだまし。
だいたい、sbrk() したら、もう返せない OS だって結構あるわけ
だし。使わないメモリは、どうせ仮想記憶に追い出されるわけだか
ら、それほど大きな害だと言うわけでもありません。
もし、free()/malloc()で、fragmentation が問題になるなら、
それを解決するべきなのであって、free()すればいいってもの
ではないと思いますね。
「万が一の時は警察なり消防が助けてくれるんだから、河原でキャンプして
もいいじゃん」ってのと、本質的に変わらんような気がします。 たぶん、
そういう人は現実に死にそうな目に遭うか、実際死んでしまわんとわからんと
思います。
まぁ、本人は自己責任の結果なんでそれでエエんですが、不幸なのは、そう
いう人に教わったりしてしまう無知な人たちですな。
+---------------------------------------------------------------------+
| From : Dairyo Gokan ( 後神 大陵 ) |
| Org. : Hitmark Computer Corporation ( ヒットマークコンピュータ ) |
| Adrs : 13256 Northup Way Suite 3, Bellevue WA 98005 |
| TEL:425-649-8808 FAX:425-649-9001 mailto:na...@can.bekkoame.ne.jp |
+---------------------------------------------------------------------+
「効率的」ぢゃなくて、単なる「手抜き」プログラミングでしょ?
自分で使うちょっとしたツールを作成するのに、細かいエラーチェックや、
入力パラメータの解析を端折って手早く仕上げるのと、実際に誰でも使える
ようなプログラムを作るのを同一視してるような気がします。
> Effective C++ でも、自前のnew()を作ることは推奨していますね。
> C++ で、destructor が必ず呼ばれてしまうのは、僕は、ある意味
> で失敗だと思います。必要もないのに呼ぶのは変だし、効率を悪く
> していることは確かです。
コンパイラに依存する問題かもしれませんが、デストラクタをヘッダ・ファ
イル内のクラス宣言で何もしないインライン関数として定義してしまえば、
コンパイルされた実行ファイル上では、全く呼び出されないと思いますが?
> malloc(),free() を必ず組で呼べば安全だってことにはならないと
> 思います。free() し忘れるってのが良くあることなのは認めるけ
> ど、どちらかといえば、free()したのに、また使ってしまったとか
> の方が危ないわけですよね。free()しなければ、そういうことには
> なりません。
こんなコト、本気で言っておられるのでしょうか?
「free()したポインタを使ってしまう人」は、「malloc()せずにポインタを
使ってしまう人」と同レベルぢゃないですかね。 確かにポインタがローカル
変数ならコンパイラが「初期化してないポインタを使っちゃダメよん☆」と
親切にワーニングメッセージで教えてくれますが、グローバル変数なら、それ
も無理ですね。
たぶんそんなヒトは、free()せずに、同じポインタをmalloc()で上書きして
使いまわすようなコードを「効率的」とか言って自慢げに書いてしまう気が
します。
> GC や、exit() の方がはるかに安全なことは確かだと思う。人の
> 感に頼って free() するのって、そんなに安全なことじゃない
> と思いますね。alloca() とかの方がまだまし。
少なくとも、本当のプログラマは「感に頼って free() する」なんてプロ
グラミングスタイルじゃないことだけは確かです。
> だいたい、sbrk() したら、もう返せない OS だって結構あるわけ
> だし。使わないメモリは、どうせ仮想記憶に追い出されるわけだか
> ら、それほど大きな害だと言うわけでもありません。
本気で言ってるのでしょうか? 組込装置や家電などを含めて考えれば、
現実に稼働してるコンピュータのうち、仮想記憶がないシステムや、メモリ
に厳しい制限があるシステムのほうが、どれだけ多いか承知した上での発言
なんでしょうか?
研究室のUNIXマシンしか頭に浮かばないような貧困な発想ぢゃ、どうしよう
もないですが...。
たとえ仮想記憶を備えたOSであっても、実際には使われていないメモリを
free()しないことで、それを要求したプロセスが存在し続ける限り不必要な
スワップアウトが発生してシステム全体のパフォーマンスが低下することは
「大きな害」以外の何者でもありません。
> もし、free()/malloc()で、fragmentation が問題になるなら、
> それを解決するべきなのであって、free()すればいいってもの
> ではないと思いますね。
なんか、問題の本質をまったく理解されてない気がします。
あらら、私の言いたいのとはちょっと違う...。(^_^;)
プログラムを書くのにきっちりとしたデータ管理は必要
です。いらないものはいらなくなったときにそう宣言し
たほうがいいのは間違いない。「free()したのに」何か
悪いことが起こったとしたら、その原因を「free()した
こと」に求めるのはおかしいです。
というわけで、自分がいまどれだけのメモリーをどこで
使っているかをプログラムを書くときに考慮することは
大事なのだけど、たとえばプログラムでずーっと抱えて
いるべきデータがあって、それがプログラムの終了とと
もに不要になるという場合なら、それをわざわざfree()
するこたあないでしょ、というのが私の感覚に近いでし
ょうか。
> GC や、exit() の方がはるかに安全なことは確かだと思う。人の
> 感に頼って free() するのって、そんなに安全なことじゃない
> と思いますね。alloca() とかの方がまだまし。
これに必ずしも同意できるわけではないのですが...。
使い終わったメモリーはfree()しておけばシステムがど
うにかして効率よく再利用してくれるだろう、と安易に
考えるのはよくないことってたしかにありますよね。
うががー。
「プロセスの終了時にそのプロセスが確保したメモリー
が自動的にきちんと解放される」というのは「プロセス
の終了時にそのプロセスそのものが占有しているメモリ
ーが自動的にきちんと解放される」のと同じレベルの話
でしょう? 後者については心配しなくてよいのに前者に
ついては心配しなければならない、というのはおかしな
話です。
OSが生成したプロセスの後始末はOSがつけるのが当然で、
それを「万が一」と表現するのはどうかなあ...。
うごうご、る~が。(T_T)
プロセスの実行コードを読み込むためのメモリを確保したのはOSですが、
プロセス内のコードが確保したメモリの管理はプロセスの責任でしょう。
ただそれでは、デキの悪いプログラムを走らせると、システムが停止した
り、メモリリソースが減って、揚げ句にゃ「OSのデキが悪い」なんて言われ
てしまうんで、OS側が気を利かしてこうした機能を持ってるだけの話でしょ。
子供(プロセス)の不始末は親(OS)の責任だから、子供は何をしてもよい
とか、街中で市民(プロセス)がポイ捨てしても、街を清掃するのは行政(OS)
の責任だから、ゴミを拾わなくて良いと言ってるようなモンです。
悪戯をしない子供がいなければ保護者はいらんし、ごみをポイ捨てする
バカがいなきゃわざわざ行政が清掃しなくても済むんですが、まぁ世の中
そう都合よくいかんので、これらのシステムがあるわけです。
> OSが生成したプロセスの後始末はOSがつけるのが当然で、
> それを「万が一」と表現するのはどうかなあ...。
ぢゃあ、そのOSが生成したプロセス内でフックされた他のプロセスのエン
トリや、戻し忘れたI/Oデバイスの状態までOSで戻してくれるんでそか?
「万が一」ってのは、適切ぢゃないかも。 むしろ、「法律(仕様)では」
とかのほうが妥当かな。 いずれにしろ、こうした人達の「受けて当然の
サービスと思ってる態度」は変わらんでしょ?
ま、薄れ行く意識の中で「あの時、警告を聞いて待避しときゃよかった」
って思っても当人の責任やし仕方ないわな。
"Arita"さん、こんにちは。
> C言語の本をにはたいてい
> mallocしたメモリーをもう使わないなら放っておけば
> 終了時に自動的に解放されるので明示的にfreeしなくても良い
> と書いてあるのですが、先日ある雑誌を見ると
> 明示的にfreeしないとメモリーリークになる
> と書かれていました。どちらが正しいのでしょうか。
私の読んでいるC言語の本にはたいてい、freeしろとあるのですが(^_^;)。
freeしなかったメモリーがどうなるかはOSとアプリケーションによって違ってき
ます(^○^)。したがって、「基本的な心得としては、要らなくなったメモリーはその
時点でfreeするのが良い」となります(^○^)。
僕は以下のようにしてリークを減らす努力はしていますが。あんまり参考にはな
りませんね(^○^)。
// 定義
T* pT = NULL; // 割り当てられていないポインタは必ずNULL
// 割り当て
assert(pT); // 多重割り当ては許しません
pT = (T*)malloc(sizeof(T));
// 開放
//assert(pT == NULL); // 割り当てられていないのにfreeするな!。(使えな
いときもある)
free(pT);
pT = NULL;
原題は「Real programmer don't write Pascal.」だったはず。 死にかけ
てる脳細胞の記録が正しければ、1983年4月号あたりの「Bit」誌に、翻訳記事
が載ってます。
FM-11BSとか、メモリ空間上にVRAM等がマップされていない特殊な環境では
960KBのコンベンショナルメモリを確保できる機種もあります。
が、それはおいといて ...
DOSでプログラムを実行する、COMモデルの場合、残りの空きメモリ全体が
プロセスに渡されますが、malloc()は最終的にシステムコール(DOSのINT21H
ファンクション)を呼び出すので、そのままではmalloc()できません。
tinyモデルでコンパイルされた実行ファイルは、スタートアップルーチン
内のコードで必要メモリ(最大64KB)を残して、OSに一旦メモリを返します。
EXEモデルの場合、EXEヘッダ内にそのプログラムが必要とするスタック量
のメモリだけを確保し、スタックポインタを初期化し後、プログラムが実行
されます。
また、_dos_allocmem()/_dosfree()といった、INT21H直結のメモリ関数では
なく、標準のmalloc()/free()では、要求された単位でメモリをその都度OSに
要求するのではなく、固定長のブロック単位で領域要求/解放しています。
これはファイルI/Oと同様システムコールの呼び出しを減らすのと、小ブロ
ックの確保/解放の繰り返しによる断片化を防ぐためだと思います。
> むしろDOSで問題になるのは、子プロセスを生成すると
> きです。子プロセス生成のシステムコールを呼ぶと、そ
> のシステムコールは親プロセスのメモリー使用状態を調
> べて、使用中の末尾の領域より後ろをいったんすべて解
> 放し、そこに子プロセスをロードしてメモリー管理を子
> プロセスに明け渡します。
システムコール(DOSのINT21Hファンクション)ではそこまで面倒見てくれ
ません。 メインプロセスは、もし子プロセスのロードにメモリが不足する
ようなら、子プロセスを実行する前に、使っていないメモリ領域をfree()
して、OSに返さなければなりません。
OSにはmalloc()された領域が、実際にプロセス内で使われているか知る
すべがありません。 システムコール(OS内部の処理)が、メモリの使用状態
を知る方法は、領域がプロセスに割り当てられ(malloc())ているか、そう
でないか(free())のみです。
ですから、OSによる子プロセス生成時に、親プロセスの領域を勝手に解放
して子プロセスを実行することはありません。
> したがって、たとえば親プロセスがロードされた後で大
> きな領域Aをmalloc()し、小さな領域Bをmalloc()し、大
> きな領域Aをfree()したとすると、おそらく親プロセス
> の本体のあとに領域Aの残骸の空き領域があって、その
> あとに使用中の領域Bが存在することになります。
DOSでは、ページング方式のメモリ管理機構をサポートしていないので、
おっしゃるとうりですが ...
> この状態で子プロセスを生成すると、子プロセスに渡さ
> れるのは領域Bの直後からのメモリー空間となり、親プ
> ロセスがfree()した領域Aのメモリーがたとえ実際にOS
> に返却されていたとしても、そのことは子プロセスが使
> 用可能なメモリー空間を増やすことにはまったく寄与し
> ないわけです。
標準関数のmalloc()にはメモリ確保の際の細かい指定が可能な仕様は(環境
に依存するので)盛り込まれていませんが、少なくとも、DOSファンクション
(INT21H)では、子プロセスのロードと実行に必要な領域が解放された領域Aに
収まるなら、領域Aがあった領域に再度領域を確保するよう指定できます。
> ここで必要になるのは、メモリー管理についてのシステ
> ム寄りの知識であり、「短命の領域を確保した状態で長
> 命の領域を確保したりしない」というようなストラテジ
> ーであって、「malloc()したものは不要になったらfree
> ()する」というレベルの一般論は役に立ちません。
「malloc()したものは不要になったらfree()する」という一般論だけで
なく、「寿命の長い領域はあらかじめ先に確保しておく」というルールで
十分な問題という気がします。
また、ANSI-Cの標準関数は標準ライブラリとして有用ですが、C言語の言語
仕様の本質的な部分ではありません。
可搬性を別にすれば、ANSI-Cの規定する「malloc()/free()」を使うことは
C言語を使う際に強制されるべき問題でもありませんから、気に入らなければ
内部で自動ガーベージコレクションする独自仕様のmalloc()/free()関数なり
を作成すればよいだけではないですか? もっとも、関数が返す(渡す)値は
ポインタではなくハンドルにしなければなりませんし、ポインタを使うほと
んどのライブラリ関数の書き変えが必要になるかもしれませんが。
> いずれにしても、free()しても意味がなく、行う処理が
> 増えるだけ無駄な場合(UNIXのプロセス終了時)や、不要
> になった段階でfree()するだけでは十分ではない(DOSの
> 子プロセス生成時)などがあるわけです。いつmalloc()
> していつfree()するかはアプリケーションの性格などさ
> まざまな状況を考慮して設計するべきで、「不要になっ
> たらfree()する」という単細胞な方針ですべてを貫こう
> とするのは間違いだと思っています。
「不要になったらfree()する」で十分ぢゃないですか? free()を呼び出し
て実際にOSがメモリを解放するのにかかるオーバーヘッドなんて、ほとんど
ないに等しいと思いますが? なんで、その程度のコトを特殊な例を引き合い
に出してまで、サボるコトに固執したがるのか理由がわかりません。
Dairyo Gokan wrote:
> 「効率的」ぢゃなくて、単なる「手抜き」プログラミングでしょ?
それはそうです。(^^)
> > malloc(),free() を必ず組で呼べば安全だってことにはならないと
> > 思います。free() し忘れるってのが良くあることなのは認めるけ
> > ど、どちらかといえば、free()したのに、また使ってしまったとか
> > の方が危ないわけですよね。free()しなければ、そういうことには
> > なりません。
>
> こんなコト、本気で言っておられるのでしょうか?
河野さんは、こういう事を、あえて「本気で」言う人です。
初心者の「のび太君的」願望を「ドラえもん的」に解決しようとするんです。
ママ:のび太、malloc()したメモリはfree()しなさい。
のび太:あぁあ、片付けるの、つい忘れちゃうんだよなぁ。
ドラえもん:はい、「がべーじ・これくたぁ」(ジャジャジャーン)
みたいな。#違うかも...(^^;
#他日、fj.sci.mathにて
# のび太:あぁあ、どう見たって 0.999... < 1 じゃないかぁ。
# ドラえもん:はい、「ちょうじゅんかいせきぃ」(ジャジャジャーン)
#これも違う?(^^;;;
多分fj歴があまりに長いため、
ありふれたツッコミに飽きてるんじゃないかと思います。
#だからボケかえす、と言うか、
#「取りあえず全部拾って、転がす」と言うか。
そういう芸風^H^Hスタイルなんです、多分。(^^;
> 少なくとも、本当のプログラマは「感に頼って free() する」なんてプロ
> グラミングスタイルじゃないことだけは確かです。
ここに茶々。
「本当のプログラマ」と聞くと、
「はPascalを書かない」と続けてしまう私。(^^;
解らない人の方が多いんだろうな、このネタ。
#今なら「SmallTalkを書かない」か、「rubyを書かない」か。
#もしかして「JAVAを書かない」?
oh...@src.ricoh.co.jpさん:
> これ、なんだかすごく納得です。しかしこの分類法でいくと河野さん
> は何屋さんになるのかな。:-)
気分屋。 久野
P.S. わー河野さんごめん! 面白いとつい書いてしまうんだよー。
> > 少なくとも、本当のプログラマは「感に頼って free() する」なんてプロ
> > グラミングスタイルじゃないことだけは確かです。
>
> ここに茶々。
> 「本当のプログラマ」と聞くと、
> 「はPascalを書かない」と続けてしまう私。(^^;
...
> ん?「本当の」じゃなくて「本物の」だったっけ?
ついでに言っておくと「書かない」じゃなくて「使わない」ではなかったでしょ
うか?
少なくとも、bitに翻訳が載った時の邦題は「使わない」でした。
原文は多分、
http://www.edfac.usyd.edu.au/staff/souters/Humour/Real.Programmer.Stories.html
--
中山隆二
nakayam...@lab.ntt.co.jp
In article <38ACB403...@cv.sony.co.jp> ,
"Takemoto,Satoshi" <take...@cv.sony.co.jp> writes
>河野さんは、こういう事を、あえて「本気で」言う人です。
そういうやつです。僕は研究の方だから、そういうことをいうべきだとも
思うしね。
>初心者の「のび太君的」願望を「ドラえもん的」に解決しようとするんです。
> ママ:のび太、malloc()したメモリはfree()しなさい。
> のび太:あぁあ、片付けるの、つい忘れちゃうんだよなぁ。
> ドラえもん:はい、「がべーじ・これくたぁ」(ジャジャジャーン)
>みたいな。#違うかも...(^^;
まぁねぇ。でも、malloc()したらfree()すればいいじゃん。ってのは、
本当は、そんなに簡単じゃないよ。実際、
いつも(malloc() したならば、いつか free())
ってのをGC抜きに検証しようと思ったら、一般的には不可能です。
(本当のプログラマは、それをどうやって保証しているのだろう?
自分で reference countするってのが C++ では多いんじゃないか
なぁ)
それよりも、GCの正当性を証明するほうがやさしかったりします。
こっちは、プログラムの振舞ではなくて、データ構造の正当性とし
て示せますから。
>そういう芸風^H^Hスタイルなんです、多分。(^^;
おもしろいでしょ?
In article <88i807$2lr$1...@epsongw6.epson.co.jp>, "Narita Takaoki" writes:
> 河野さん的には「人間のプログラムにおけるメモリ管理構造の設
> 計誤謬性を考慮すると、誤った構造に設計し難い GC による管理
> を導入した方が、より安全であろう」とでも言いたかったのではな
> いでしょうかね。
まぁ、そんなところです。
> 少なくとも、プログラミングという仕事の結果の成果物の品質に、
> 責任を負う職業プログラマから見れば、そんな態度で仕事をする
> なら辞めてくれと言われるでしょうね。
確かに、メモリリークを甘く見る気はないです。それはやっちゃいけない
こと。でも、それを防ぐ一つの方法として、
block release reserve -> malloc in module
module release -> block memory release
という手法があって、malloc -> exit っていうのは、そういう安全サイド
の手法の一つだと指摘したいな。
object の destruct だと、object がOSのシステムリソースを握っ
ていることもあるので、どうしても呼ぶ必要があるというのも理解
できるんですが、納得できないところも多いですね。
> まあ、研究室の UNIX 云々とは言わないですが、実験室レベル
> の話と実際のフィールドでの話は別ですねって事でしょうかね。
まぁ、それはそうでしょうけど。
なるほど、このあたりは私の知識では後神さんに立ち打
ちできませんね。おおむね了解です。
> EXEモデルの場合、EXEヘッダ内にそのプログラムが必要とするスタック量
> のメモリだけを確保し、スタックポインタを初期化し後、プログラムが実行
> されます。
これによって残りの空き領域すべてがmalloc()可能なヒ
ープとなるわけですよね。
> OSにはmalloc()された領域が、実際にプロセス内で使われているか知る
> すべがありません。 システムコール(OS内部の処理)が、メモリの使用状態
> を知る方法は、領域がプロセスに割り当てられ(malloc())ているか、そう
> でないか(free())のみです。
> ですから、OSによる子プロセス生成時に、親プロセスの領域を勝手に解放
> して子プロセスを実行することはありません。
私が言いたかったのは、malloc()されている領域だけを
残して、あとの部分を子プロセスに渡すということです。
親プロセスの「領域」ということばの定義をあいまいに
しておいたのが悪かったのですが...。
> 「不要になったらfree()する」で十分ぢゃないですか? free()を呼び出し
> て実際にOSがメモリを解放するのにかかるオーバーヘッドなんて、ほとんど
> ないに等しいと思いますが?
あれ? 勘違いされてしまったか...。
「free()を呼び出して実際にOSがメモリを解放するのに
かかるオーバーヘッド」ではなくて、「プログラムの終
了時にそれまでfree()されていない領域をすべて調べあ
げてfree()するのに必要なオーバーヘッド」を問題にし
ているのです。
なお、「free()する」には「free()された領域がこの次
にmalloc()されてよいようにメモリー管理データの再構
成を行う」オーバーヘッドが含まれています。
> なんで、その程度のコトを特殊な例を引き合い
> に出してまで、サボるコトに固執したがるのか理由がわかりません。
「サボるコト」に固執しているわけではなくて「サボっ
ても安全かどうかを知るコト」に固執しているのです。
「絶対にサボらないと決めておいて、サボったときにど
うなるかを知らずにすませる」のはよくない習慣だとい
うことです。
>そうとは思わないな。多量に malloc した後、ランダムな順序で free
>すると極めて遅くなる malloc はいくつかあります。このような場
それは「できの悪い実装」であって、「仕様」とは別な話です。
どうしても現場として見過ごすわけに行かない場合は、
条件コンパイルあたりを検討すべき種類の問題です。
>exit 時に、どの領域のメモリが残るかどうかは、malloc とは
>独立の問題です。そのあたりをごっちゃにすべきではないです。
御意。
ごっちゃにするから「一般的に」 free 不要という台詞に至る
のでしょう。malloc はメモリ管理、exit はプロセス管理、
それぞれ担当分野の違うものです。
>良いって教えます。exit()がcloseするのは仕様ですし、exit()で
>プロセスのメモリ領域が解放されるのも仕様ですよね。
「アプリがしたこと」全てが解放されるわけではないし、
逆に1関数の独断で解放してよい資源ばかりとも限りません。
ある特定の場面で、やるべきことをサボっても助かることを
知っているからといって、それが一般論に聞こえる教え方は
望ましくないといっているのです。(ここで言う「やるべきこと」
とは、借りたら返す、開けたら閉める、自分で蒔いた種の
落とし前は親に頼らない、などのことです)
>ようは、ちゃんと理解していればいいのでしょう?
そう、ちゃんと理解させるべきなのです。
#出張のため次のコメントは1週間弱遅れます
こいつはその通りですけれど、
| > mallocしたメモリーをもう使わないなら放っておけば
| > 終了時に自動的に解放されるので明示的にfreeしなくても良い
こういう一般化ってのも問題ないですかね?
本来は「返却すべき」であるが、ほっておいて問題ない場合に
限り「 (exit でも free でもいいが) 最後にまとめてやれば
よろしい」ってだけのことで。
# free をいちいちするので時間を食うのはばかばかしいけど、
# それで資源が圧迫されたらばかばかしい、じゃ済まない場合
# もあるでしょうから。
--
みんつ - mi...@minz.org - http://www.minz.org/ - みぎまつ・ひろし
> 使っているかをプログラムを書くときに考慮することは
> 大事なのだけど、たとえばプログラムでずーっと抱えて
> いるべきデータがあって、それがプログラムの終了とと
> もに不要になるという場合なら、それをわざわざfree()
> するこたあないでしょ、というのが私の感覚に近いでし
> ょうか。
私もこれに似たような感覚でもって、quick & dirty プログラムでは
fcloseしなかったりXtDestroyApplicationContextを呼ばなかったりします。
ていうか、後者を呼び出しているプログラムは、まず見ないですね。
Xではプログラマーの意識レベルでサーバー側のリソースを丁寧に
破棄して回るプログラムを書く方が珍しいような気がします。
たいていはリソースの破棄をGUIライブラリやXの仕掛けに任せてしまいます。
サーバーとの接続が切れたら、自動的に破棄されることになっています。
XImageオブジェクトも(ファイルから読み込んだ画像と交換するときならともかく)
終了時に破棄していないものがほとんどなので、クライアント側でも
場合によっては(対象によっては)一般的かもしれません。
> In article <38AB7D...@geocities.co.jp>, Arita writes:
<中略>
> なので、「終了時ならば明示的にfree する必要がない」という方が
> 普通でしょう。
> それでも free しろっていうのって、せっかく塵取りの上にのって
> いるのに、ピンセットで一つ一つゴミ箱に移しているようなもので
> す。
例のOSではそうはいきませんよ。そういうOSがある以上、freeを使わないのは、移植性を
損ねます。
> んー。一部OSはmalloc()相当のものが共有メモリの割り当て
> と等価だったりもしますんで、そういうのはあるかも。
ないと思っていましたが、あったんですか。
Cの仕様上全く問題ありませんが、マルチタスクのOSとしては不適切ですね。
勉強になります。
> そういうことなら、ルールを遵守しようとする人はその
> ルールがどういう意味をもっていて、どうして守らなけ
> ればならないかを理解する必要があるだろうと私は考え
> ます。理解せずに言われたことを守るだけ、という姿勢
> が望ましいものであるとは思いません。
今回の問題では、仕様を守ることが、移植性の向上につながる。
なぜなら、仕様を守ることで、移植性を保っているからです。
仕様を守らなかったら、移植性が失われて当然のことだから。
が、適当な理由でしょうか?
>元記事の方は、そのようなmalloc()の使いかたをしてい
>るときに使い終わったメモリーをfree()しなくてよいか
>とお尋ねなのではないでしょう。
いや、お尋ねなのだと思いますよ。
「malloc したら free すべきか? (長期稼動を除く)」
こんな除外が書けるような人は、
そもそもこんな質問をする必要がない人でしょう。
もっとも、紛糾している様を見て楽しみたかったのなら
別ですが。
>むしろ、そのようなプログラムが長々と稼働したあとで
>仕事を終えて終了する直前に、それまで確保していたこ
>まごまとしたメモリーをすべての個別に解放することが
>本質的に必要なのかをお尋ねなのだと思います。
どうして「こまごま」と感じるのでしょうか。
資源を要求する各モジュールの中で、自分の後片付けだけを
やっていればよいことで、後片付けの数をパーツの数で割る
とリーズナブルな数になっているはずです。
始めに exit ありき、で考えることによる数のトリックでしか
ないでしょう。
このあたりは太田さんとは対立していないと思っていましたが?
UNIXのプロセスの保護に依存していますね。
それ以外の環境のことを考慮していません。
実際には、Windowsのような余りよくないシステムの方が多いのですから。
UNIXでも物によっては、mallocで共有メモリを確保する物もありますし。
exitで必ずメモリを解放するということは規定されていません。
よって、freeを使ってメモリを解放しなければ、OSによってはトラブルの原因となりま
す。
ただし、exitで必ずメモリを解放するということは規定されているOSだけをターゲットに
するなら話は別ですが。
> >仕様を守らなかったら、移植性が失われて当然のことだから。
> >が、適当な理由でしょうか?
>
> 適当? 移植性が組み込み機器とかを指すなら、malloc()/free()を
> 予測可能な範囲で処理することの難しさに着目すべきですね。
移植性とは、違う環境でも動くことが保証されると言うことです。
たとえば、UNIXでもDOSでもWindowsでも問題なく動くと言うことです。
まあ組み込み機器も一応その中に入りますが(ただし、仕様にあっていること)。
言葉の意味を誤解していませんか?
仕様とおっしゃいますが、それをいうなら
malloc()/free()の組み合わせではOSから割り当てて
もらったメモリーをOSに返却したと保証することは
プログラムからでは不可能
というのがmalloc()/free()というインターフェースの
仕様です。いいかえれば
malloc()したメモリーすべてをfree()しないで終了
するプログラムはトラブルを起こす、という仕様の
malloc()/free()インターフェースを実装することは
malloc()/free()インターフェースの移植性を低下さ
せる重大な違反
だろうということです。
ちなみに、ANSI Cではfree()について「領域を解放す
る、すなわち、以降のmalloc()でその領域が再利用さ
れるようにする」という意味のことが書かれていたは
ずです。
その特殊な環境のmalloc()やfree()のマニュアルにど
ういうことが書かれているのか興味ありますね。
消えたかどうかfree()で確認できますか?
ごくろうさまです。
> いや、お尋ねなのだと思いますよ。
> 「malloc したら free すべきか? (長期稼動を除く)」
> こんな除外が書けるような人は、
> そもそもこんな質問をする必要がない人でしょう。
元記事の質問は「終了時に自動的に解放される」と「メ
モリーリークになる」のどちらが正しいのか、というも
のですから、自分がmalloc()したメモリーの「プロセス
終了時の挙動」を尋ねているのは明らかです。
# プロセス稼働中に不要なメモリーをそのままかかえて
# いることを「メモリーリーク」とはいわない。
そういう環境でmalloc()/free()のような「メモリーを
OSに返却できたかプログラムから確認のしようがない」
インターフェースを使うことのほうが、よほどトラブル
の原因のような気がしますが、いかがですか?
プログラムで責任をもってOSにメモリーを返却すること
を奨励するなら、そのための関数は少なくとも正しく返
却できたかどうかを返り値として返す仕様のものでなけ
ればならないでしょう。free()はそうではない。
ゴミの比喩でいえば、free()するというのはゴミ箱のほ
うにゴミを放り投げて、あとは知らんぷりをしているよ
うなものです。free()を使うかぎり、それ以上のことは
そもそもできないのです。
それは正しくないと思いますよ。
free()した時点でOSに返せないのならmalloc()/free()
がOSにメモリーを返す一般的な方法はありません。どこ
にもそのためのフックはないのですから。
そういうものでも「返せる」ようになっているなら、そ
のメモリーがmalloc()されたままのものでもfree()で解
放済みのものでも区別なくOSに返せるようになっている
のが当然でしょう。
> 要するに、freeを使わないためにトラブルが起こった場合は、プログラマーの責任だと思
> います。
free()を使ってもプログラマーが責任をとれるわけでは
ない、ということを私は示したつもりです。
> mallocは、どこからリソースを得るのかが規定されていません。
> 共有メモリから確保するOSもあるようです。
> しかし、仕様には反してはいないと思います(マルチタスクOSとしては不適ですが)。
> こういう環境もある以上、freeを使ってメモリを解放しなければ、トラブルを起こす環境
> が存在するので、移植性が低いといえるでしょう。
それは「free()しないで終了するプログラムの移植性が
低い」のではなくて「malloc()/free()というインター
フェースの移植性が低い」のです。
> 共有メモリから確保するOSもあるようです。
というような環境では、そもそもmalloc()/free()をほ
かのOSと同じ目的で使うべきではないでしょう。
malloc()/free()がいかにも移植性がありそうなふりを
してそういう方針で実装されている環境があることにつ
いては、事実ならたしかに問題ですし、そのことに触れ
ておくのは悪いことではないですね。
ただ、そういう環境なら、おそらくmalloc()されている
すべてのメモリーを一律にOSに返却するような関数が用
意されているのではないかと思います。
すべてのメモリー割り当てはmalloc()経由で行われるの
でしょうし、malloc()/free()パッケージはどれだけの
メモリーが使用中であるかについて知っているわけです
から、malloc()されたままのものであれ、free()された
ものであれ、自分を通じて割り当てられたメモリーをす
べてOSに返すのは簡単なことです。
しかも、malloc()/free()パッケージのほうですべての
メモリーをOSに返却するなら、malloc()を呼び出したプ
ログラムの側で自分でデータ構造をたどってfree()しま
くるよりも安全確実に処理が行えるわけですし、free()
では不可能な「ちゃんとOSに返せたよ」情報もプログラ
ム側に伝えることができるわけです。
そういう環境を用意しないで、共有メモリーをただその
まま使ってmalloc()/free()を実装しているOSがあると
いうのは、私には信じがたいことですが。
「プロセスの終了前に自分ですべてfree()すればOSにす
べてのメモリーを返却したことになる」というmalloc()
/free()の実装にはどんなものがあり得るか考えてみま
した。可能性があるとしたらこんなものでしょう。
(1) malloc()とfree()はじつはOSのメモリー確保/解放
のシステムコールをそのまま呼んでいるだけ。
これでは細かいメモリー確保/解放のタイミングで
システムコールが発生するわけで、まったく非効率
です。しかも解放にfree()を使う以上、正しく解放
されたかどうかをチェックする方法が存在しないわ
けで、危険このうえない。こんな形でシステムコー
ルにmalloc()/free()の皮をかぶせるというのはあ
ってはならないことです。
(2) malloc()は必要に応じて大きな単位でOSからメモリ
ーを確保して、それを細切れにして呼び出し側に返
す。free()は返されたメモリーがまとまった単位に
なるとOSにそれを返す。
境界条件が存在することになり、その境界で細かい
malloc()/free()を繰り返すと効率が落ちます。こ
のときの効率はmalloc()が内部でメモリー管理をし
ている分だけ(1)よりさらに悪くなります。
(3) (2)と同じだが、free()ですべてのメモリーが解放
されたときだけOSにそれらのメモリーを返す。
本質的に(2)と同じで、メモリーがひとつも確保さ
れていない状態で細かいmalloc()/free()を繰り返
すと(2)と同じ状態になります。
「プロセスの終了前に自分ですべてfree()すればトラブ
ルを起こさなくてすむ」という主張の人で、それが可能
になるようなmalloc()/free()の実装を示せる人はいら
っしゃいますか?
ひとつの要素を検索して解放するコストがO(log n)とす
ると、n個の要素があるからO(n log n)かな? logの底は
B木の構造によるでしょう。
なかなかよい例を出されましたね。さらに駄目押し。
「プロセスの終了時に自分ですべてfree()すべきだ」と
お考えの人は、free()にどれだけのコストがかかるかあ
まり考えていらっしゃらないようです。
free()ではそれ以降のmalloc()で領域が再利用されるよ
うに、解放されたメモリーをフリーリストにつなぎなお
す必要があります。それだけでもよけいなコストがかか
るのに、効率を考えたmalloc()/free()パッケージだと、
メモリーが有効に再利用されるように、連続した小さな
ブロックがすべて解放されたらそれらをまとめてひとつ
の大きなブロックにしたりします。
つまり「malloc()で確保したすべてのメモリーを個別に
free()するコストの総計」は「確保したすべてのメモリ
ーをまとめて解放するコスト」より飛躍的に大きくなる
ということです。
しかもこれらが上のO(n log n)で効いてくるわけですか
ら「個別にfree()するのはたいしたコストじゃない」と
いう意見には私もまったく同調できないです。
逆にいうと、終了時にすべてのメモリーを解放しなけれ
ばならない環境では、malloc()/free()インターフェー
スにも再利用を考えずにすべてのメモリーを解放する関
数が当然存在すべきで、それを使うことのほうがいちい
ち個別にfree()を呼ぶより奨励されるべきでしょうね。
それ言ったら、exit()でちゃんとプログラムが終了したかどうか確認でき
ますか? free()の実装が正しくて、malloc()したポインタがfree()の引数
として渡されてれば、解放されるのは仕様です。(OSにちゃんとメモリを戻す
かどうかはmalloc()/free()の実装に依存する個別の問題です)
冷蔵庫のドア閉めたら、中のランプがちゃんと消えたかどうか確認でけん
のと一緒でせう。
> malloc()したメモリーすべてをfree()しないで終了
> するプログラムはトラブルを起こす、という仕様の
> malloc()/free()インターフェースを実装することは
> malloc()/free()インターフェースの移植性を低下さ
> せる重大な違反
> だろうということです。
必ずトラブルを起こす訳ではなく、トラブルを起こしても、仕様どうりに動いているから
しょうがない。
ということでしょう。
それとも、初期化されていないポインターのしめすアドレスに書き込みを行った場合トラ
ブルを起こすような仕様は、ポインターの移植性を低下させるというような感じで書いた
のでしょうか?
もし、freeを使ってメモリーをちゃんと解放しないために動作しないことは、Cのシステ
ムとしては問題ありませんが、freeでちゃんと解放したことによりトラブルが起こるよう
なことは、システムに異常がない限り起こりません。
要するに、freeを使わないためにトラブルが起こった場合は、プログラマーの責任だと思
います。
> ちなみに、ANSI Cではfree()について「領域を解放す
> る、すなわち、以降のmalloc()でその領域が再利用さ
> れるようにする」という意味のことが書かれていたは
> ずです。
確保したまま解放しなければ、空きメモリが減ります。
> プログラムで責任をもってOSにメモリーを返却すること
> を奨励するなら、そのための関数は少なくとも正しく返
> 却できたかどうかを返り値として返す仕様のものでなけ
> ればならないでしょう。free()はそうではない。
それもそうですね。
まあ、返却に失敗されてもどうしようもありませんし。
仕方ないですね。
例の共有メモリを使うタイプだったら、freeを使わないと、大変ですから、一応書いてお
くべきだと思います。
> ゴミの比喩でいえば、free()するというのはゴミ箱のほ
> うにゴミを放り投げて、あとは知らんぷりをしているよ
> うなものです。free()を使うかぎり、それ以上のことは
> そもそもできないのです。
仕様では、私たちは、どうすることもできませんね。
Windowsでは、そんなような機能が、一応搭載されているようですが(mallocではないです
が)。
Windowsのシェアが世界一である間は 執着しなくてはいけない
人間は沢山いるでしょうねぇ。
-----
Yasuhiro.Yao
ワーキングセットが大きくなり、結果としてページ違反やキャッシュミス
が発生して性能が低下する現象ですね。
未使用な未解放領域が増えると、こういった現象が起きます。
-----
Yasuhiro.Yao
> そういうものでも「返せる」ようになっているなら、そ
> のメモリーがmalloc()されたままのものでもfree()で解
> 放済みのものでも区別なくOSに返せるようになっている
> のが当然でしょう。
ほんとだ。free()で解放できるとしたら、当然exit()でも解放できるはずです
ね。だとすると、free()したほうが良い場合がもしありうるとしたら、
プログラムが異常終了してfree()もexit()も呼ばれないと、メモリがOSに返
却されない環境がある。その時の被害を軽減するため、なるべく早めにfree()
しておく。
という場合でしょうか。 ただ、このような環境で可能なのはせいぜい「軽減」
にすぎませんから(mallocしたメモリを使用中に死んだらどうしようもない)、
このようなOSでは、信頼性のあるメモリ返却は本質的に不可能ということにな
りますね。freeするコードを入れたからといって安心できるものではない。
# やっぱり『実装の質が低い』としてあきらめるしかないのでは。
いずれにせよ、標準Cの範囲を外れた話ですね。(異常終了した時に何が可能か
なんて、移植性の高い話ができるわけもない。)
前田敦司
必要ないのは知っています。
> こんな人ばっかりがプログラミングしているの? Windows って...
> そりゃ、アプリケーションが遅くなるわけだ。
プログラムのエラー検出ツールであるNu○ega社の○ounds○heckerと言う
開発支援ツールは、アプリ終了時に解放していないメモリ領域が存在
すると、メモリリークがあるとして警告します。
まぁ、どれだけの人が○ounds○heckerを使っているかからはわかりませんが、
高価な市販品がすることですから錯覚する人は多いはずです。
そしてその状況を起因として、終了時に全てfreeすべきという「常識」が生まれて
しまったり。
言語仕様や、OSのメモリ管理の仕様まで掘り下げてことを考える人は少
ないですから、市販品が「法律」になってしまうんですかね。
某有名OSのソフトウェア会社が築いたような・・・・・(笑)
(Windows3.1の後遺症ってのもあるかも?こいつは終了したアプリの未解放
領域が沢山あるとよくご機嫌ななめになりました。)
メモリを食いつぶしてOSや他のソフトウェアの動作に影響を与えなければ
それで良いと思いますがね。
終了時は、そのアプリはそれ以上動作しないのだから、OSに任せてしまって
構わないでしょ。
-----
Yasuhiro.yao
> メモリ管理の安全性の向上と、速度の向上は両立します。そして、
> たこなメモリ管理とそうでないものの差は、2-3倍あると言われて
> います。もし、単純に、malloc()/free() しているのならば、根性
> を入れ換える必要がありますね。つまらない最適化よりも、本質的うきょう
> な問題だし、他のプロセスにも影響を及ぼします。
>
> 例えば、クロスリファレンスのプログラムを考えましょう。こいつ
> は、クロスリファレンスを例えばB-Treeかなんかで作っていきます。
> これが解放されるのは、クロスリファレンスが終了して、表示し終
> った時でしょう。もちろん、プログラムは、free()せずに exit()
> して構いません。さて、これを、free() した時の計算量はいくつ
> でしょうか?
>
> exit()時の不要な全領域のfree()は、「計算量的にやっちゃいけな
> いプログラミング」であって、プログラマは、そのような ことに鈍
> 感であってはならないはずです。
>
> お、「最初に、まとめてmalloc()して、そこから自分でセルを作って
> とっていけば良い。最後もfree()一発で良い」ですか? 良いところに
> 気付きましたね。それは、malloc()->sbrk()->exit() の再発明です。
システムに依存した物であり、物によっては書いてありません。
> > > 本当にmalloc()/free()という名前で、ですか? 後学のためにどういうシステ
> > > ムか教えていただけますか?
> > デフォルトヒープでWindowsのHeapAllocを呼んでいるだけ。
> > このAPIは、mallocと同じような方法で確保しているので、あまり遅くありません。
>
> 標準Cのmalloc/freeの話ではないんですね。じゃあこのスレッドとは無関係で
> すね。
mallocがHeapAllocを呼んでいる物があるということです。
freeは、HeapFreeを呼んでいました。
次も同じです。
<中略>
> そんなことができるくらいなら、「exit()時に(あるいはmainからreturnする
> 時に)すべてのメモリをOSに返す」としてあるのでは。
そうなっていれば問題はないのですが、そうなっていない物もあるから困っているので
しょう。
> malloc()/free()という名前の関数の実装の話をしてるわけですが、そのアプ
> リケーションがいったいどういう関係が? 古田さんはそのアプリケーション
> の中のmalloc/freeを使ってプログラムを書くのですか? そして、皆それを考
> 慮してプログラムを書かなければいけないという事でしょうか?
もとからあったソフトで、私が作った物ではありません。
printfやgetcに類似した関数が多数あり、標準関数以外のルーチンが利用されていないこ
とから、C言語で書かれていると思われます。
そのコードを生成したシステムのライブラリに含まれていると言うことです。
> > > > 実際にあるのですから、これらの環境も考慮しなくてはなりません。
> > >
> > > 標準Cにしたがって正しく動かない実装を標準Cの範囲で「考慮」するのは不可
> > > 能です。
> > 一応、遅いですが正しく動かないことはないでしょう。
> 上の私の文章で「正しく動かない」という言葉は(malloc/free/exit等の)実装
> にかかっているのであってあなたの書くプログラムの話ではありません。
私の書くプログラムのことではなく、
(1)(2)の実装の話です。
書かれている環境もあります。書かれていないとすれば、
それはプロセス終了時にOSが後始末として行うべき処理
のひとつであって、ユーザープロセスの側で行う処理で
はないからでしょう。
「exit()を行うとそのプロセスが占めていたメモリー空
間はすべてOSに返却される」というのと同じレベルの話
ですから、exit()の説明にわざわざ書かれていなくても
おかしなことではありません。
> 移植性とは、別の環境で動く間での手間が少ないことで、より多くの環境で同じ字面のプ
> ログラムがそのまま動けば、非常に高いことになります。
そういう単純な視点で「移植」が行われているとしたら
ユーザーにとってはずいぶん不幸な話ですけどね。
同じ字面のプログラムがある環境ではじゅうぶんな効率
で動くものの、別の環境ではきわめて非効率な動きをす
るとすれば、それは移植性の高いプログラムではありま
せんよ。
移植するとは、同じ目的のプログラムが同じような効率
で動くように別の環境に移し変えることでしょう。その
ためにはプログラムが意図している処理内容に対応する
関数を新しい環境で選んで利用することが必要で、同じ
名前の似たような処理をする関数があったとしても、あ
えてそれを使わないこともあります。
# そのための判断の拠りどころとなるのが標準規格であ
# って、標準規格に従っていない環境にプログラムを移
# 植するときには、用意されている関数の動きをすべて
# 自分で検証する必要があるわけです。
「同じ名前の似たような処理をする関数」を使ったとし
たら、「とりあえず動く」までの手間は少なくなるかも
しれませんが、「ちゃんと動く」までの手間はかえって
増える可能性が高いです。
これらのいずれでもなく、
(C) ANSI Cとして、free()はOSにメモリーを返す関数で
はなく、malloc()/free()インターフェースにメモ
リーを返す関数であることが明記されている
が示せればそれでかまわないでしょう。
このような仕様のメモリー割り当て/解放インタフェー
スがまともに使えるためには、プロセス終了時にこのイ
ンターフェースがかかえているメモリーが、何らかのメ
カニズムで確実にOSに返却されることを暗黙のうちに保
証する必要があるからです。
最新のANSI Cは見ていないのですが、ANSI C標準草案で
は「free()は渡された領域をdeallocateする、すなわち、
以降のmalloc()でその領域が再利用されるようにする」
といった文面になっていたはずです。deallocateの意味
が念を押してこのように記述されているからには、(C)
が示されているとみてよいでしょう。
なるほど、具体的には何というソフトですか? また、リ
ンクされているライブラリーの内容からコンパイルに使
った処理系は推定できませんか?
いずれにしても、そのmalloc()/free()はANSI C準拠の
関数ではなく、独自仕様のものとして実装されている可
能性が高そうです。
> Windows が問題になっていますが、これも Win16 と Win32 で違います。
> 「終了しても OS に返さない」という意味でのメモリリークが発生するのは
> 基本的には Win16 だけのはずです(Win32 はそれなりに(?)しっかりして
> います)し、その点で問題になる関数は malloc/free ではなく、システム
> コールの GlobalAlloc/GlobalFree のほうです。
> #LocalAlloc/LocalFree というシステムコールもあります。
ですよね。malloc/freeの場合、ライブラリで管理してる使用中の領域をOSに
返すルーチンをatexit()で登録しとけばいいわけですから...
ふつー誰が書いてもexit()時に返却されますよね。
> Win16 ではメモリ空間がプロセスごとにしっかり分離されていませんので、
> 下手に GlobalAlloc を使うと、終了しても解放されないメモリが残ります。
> ちなみに、Win32 では GlobalAlloc は LocalAlloc と等価とされています。
まあ、システムコールを直接使うよなアブナイ(高度な?)話だと、もともとア
ブナイことが起きてもしょうがないですよね。
前田敦司
> システムに依存した物であり、物によっては書いてありません。
「物によっては書いてありません」? まあ当り前です。
exitした後に何が起きるかはCの守備範囲の外ですから、基本的には書いてな
くても当然ですね。すると、あと標準Cの範囲でできることと言えば、標準Cが
想定している機能を満たす実装で正しく動くプログラムを書く事だけじゃない
ですか。
ところで、malloc()で割り付けたメモリ(Globalなんとかというシステム依存
のシロモノじゃなくて)が、exit()では解放されない仕様だと明記したドキュ
メントを1つでも示していただけます?
前田敦司
> ここに茶々。
> 「本当のプログラマ」と聞くと、
> 「はPascalを書かない」と続けてしまう私。(^^;
> 解らない人の方が多いんだろうな、このネタ。
確かに、FORTRAN ならこんな議論は起きなかったでしょうね。(^_^)
# 私は、Pascal 大好きな、キッズプログラマーですが...。
--
--------------
電子のお針箱
ue...@di.mbn.or.jp
(From: ヘッダーはスパム対策のため -nospam を付加しています。)
--------------
> > でも malloc は free する「仕様」の関数です。
> これは正しくないのではないですか?
> malloc()がシステムからメモリーをもらってくる関数で
> あることは正しいのですが、free()はその逆をする関数
> ではないのです。free()はむしろ、そのあとでmalloc()
> を行ったときに再確保されるメモリーを用意する関数と
> とらえたほうがいいでしょう。
free() の仕様はあくまでも、malloc() した領域を開放するための関数ですよ。多
くの実装が、解放した領域を領域を OS に返さないようになっているからと言って、
free() した領域がいつまでもプロセスが所有していると言う保証はありません。実
際、VC++ 4.0 のヘルプでは、free() すると OS にメモリーを返すこともあると書い
ています。(WindowsNT のみですけどね。)
> malloc()したものは無条件にfree()すべきだと教えるこ
> とは、その非対称性に気づくチャンスを奪うことにもつ
> ながりますよね。
malloc() したものを free() し忘れることは、malloc()/free() の実装を知るこ
とより重要でしょう。だから、初心者には malloc() したものは常に free() すべき
と教えるべきです。
実装を知ってより効率の良いプログラムを書くのはその後で良いと思います。
> まぁねぇ。でも、malloc()したらfree()すればいいじゃん。ってのは、
> 本当は、そんなに簡単じゃないよ。
常に、malloc()/free() が対にできるとは言いませんが、ほとんどの場合可能だと
思います。どう言う場合に、難しいのでしょうか ?
> 実際、いつも(malloc() したならば、いつか free())
> ってのをGC抜きに検証しようと思ったら、一般的には不可能です。
この意見は正しいですが、検証できないから free() しなくても良いと言う訳では
ないですよね。
> (本当のプログラマは、それをどうやって保証しているのだろう?
> 自分で reference countするってのが C++ では多いんじゃないか
> なぁ)
それをコンパイラに保証させるために、コンストラクタ/デストラクタがあるので
す。でも、まだ心配だから机上デバック、長時間連続稼動試験、市販のメモリー
チェッカツールなんかでやるのが普通でしょ。
> それよりも、GCの正当性を証明するほうがやさしかったりします。
> こっちは、プログラムの振舞ではなくて、データ構造の正当性とし
> て示せますから。
GC なんて使えない状況と言うものを知らないのでしょうか ?
> > 少なくとも、プログラミングという仕事の結果の成果物の品質に、
> > 責任を負う職業プログラマから見れば、そんな態度で仕事をする
> > なら辞めてくれと言われるでしょうね。
> 確かに、メモリリークを甘く見る気はないです。それはやっちゃいけない
> こと。でも、それを防ぐ一つの方法として、
> block release reserve -> malloc in module
> module release -> block memory release
> という手法があって、malloc -> exit っていうのは、そういう安全サイド
> の手法の一つだと指摘したいな。
そう言う手法に加えて、アプリケーション側でもできるだけ手当てするのが普通で
> OSがプロセスに割り当ててくれるのはメモリー空間であ
> って、その中にはコードがロードされるテキスト領域や
> コードが消費するスタック領域やプロセスがmalloc()で
> 使うヒープ領域などがあるわけです。この中をどう使お
> うとプロセスの自由で、プロセスの終了時にはOSがこの
> メモリー空間全体を回収するものでしょう?
思いっきり、Unix や Windows しか考えていない意見ですね。組込み用の OS 等で
は、「ヒープの管理は全部アプリケーション側でやってね。」と言うスタンスのもの
は少なくないですよ。
> MAEDA Atusi <ma...@is.uec.ac.jp> wrote in message
> news:pypog9c...@tp560e.sowa.is.uec.ac.jp...
> > "Furuta" <furut...@ma2.justnet.ne.jp> writes:
>
> > > > 本当にmalloc()/free()という名前で、ですか? 後学のためにどういうシステ
> > > > ムか教えていただけますか?
> > > デフォルトヒープでWindowsのHeapAllocを呼んでいるだけ。
> > > このAPIは、mallocと同じような方法で確保しているので、あまり遅くありません。
> >
> > 標準Cのmalloc/freeの話ではないんですね。じゃあこのスレッドとは無関係で
> > すね。
> mallocがHeapAllocを呼んでいる物があるということです。
> freeは、HeapFreeを呼んでいました。
> 次も同じです。
なんという処理系のどういうバージョンでしょう? メモリ要求をまとめずにそ
のままHeapなんとやらを呼んでるという事はどうやって確認なさったのでしょ
う?
> <中略>
> > そんなことができるくらいなら、「exit()時に(あるいはmainからreturnする
> > 時に)すべてのメモリをOSに返す」としてあるのでは。
> そうなっていれば問題はないのですが、そうなっていない物もあるから困っているので
> しょう。
なんという処理系のどういうバージョンでしょう? exit()時にメモリを返して
いないという事はどうやって確認なさったのでしょう?
前田敦司
> まぁねぇ。でも、malloc()したらfree()すればいいじゃん。ってのは、
> 本当は、そんなに簡単じゃないよ。実際、
> いつも(malloc() したならば、いつか free())
> ってのをGC抜きに検証しようと思ったら、一般的には不可能です。
> (本当のプログラマは、それをどうやって保証しているのだろう?
> 自分で reference countするってのが C++ では多いんじゃないか
> なぁ)
私だったら、こんな方法使いますよ。
プログラムの所々でログ取らないと、どこで、ミスしてるかわからなくなりますが。
あと、結構いろいろテストして、各部分をチェックすると、ほぼ確実です。
...
#include <malloc.h>
void * deb_malloc(size_t s);
{
void *pv;
pv = malloc(s);
//ここでファイルにログを取る。
return(pv);
}
void deb_free(void *pv)
{
free(pv);
//ここでファイルにログを取る。
}
#define malloc deb_malloc
#define free deb_free
...
> いずれにしても、そのmalloc()/free()はANSI C準拠の
> 関数ではなく、独自仕様のものとして実装されている可
> 能性が高そうです。
動作が同じですから、移植性は大丈夫だと思いますよ。
> しかしこれをもって「プロセス終了時におけるfree()は不要である」という一般論を
> 導き出すためには、
>
> (A) すべてのOS上で、malloc()が使用するヒープ領域はプロセス終了時にOSに返され
> るという実装になっている。
> (B) ANSI Cとして、malloc()が取り出した領域はプロセス終了時に(free()しなくとも)
> OSに返されることが規格に明記されている。
>
> の、いずれかも同様に示さなければならないでしょう。
free()してもムダである事が言えているので十分ではないでしょうか。
> なぜならば、元記事はOSの名称には言及していないため、特定のOSに依存した答えを
> 出しても一般解としては正しくないからです。
free()すると正しく動くが、exit()では正しく動かないOSがあると言うこと自
体私はまだ信じられないのですが。(そういう実装ではfree()してもダメでしょ
う?)
たとえそういう実装があったとしても、元の質問者のような初学者(かな?)に
対して、標準的な答えでなく(特殊な|劣った|古代の|信頼できない)環境にお
ける(奇矯な|不合理な|苦痛に満ちた|まじないめいた)プログラミング習慣ま
で考慮するように強制するのはあまり良くない事だと思います。
> どのOSで動く処理系かもわからずに「OSが面倒みてくれるんだから不要な関数など
> 呼び出さなくていいんだよ」という態度をとることも結構ですが、そのためには「本
> 当にどのOSでも面倒みてくれる」という裏をとることが必要ではありませんか。
そうでないOSは、標準的なCの守備範囲を外れたシステムという事になると思
います。これから勉強しようというような人が手を出さない方が賢明でしょう。
(Unix系のすべてのOSやWindows95/98/NTやDOSでは大丈夫みたいですし、いま
まで実際ダメなOSの実例っていうのが挙がっていない以上、まあたいていのプ
ラットフォームでは大丈夫と思って良いのでは? それ以上の変な環境への考慮
まで求めるのは酷でしょう... 別に『すべての環境でそのまま動く』Cプログ
ラムを書こうなどというムチャな野望に燃えてるわけでもなさそうですし。)
前田敦司
記事 <88orp7$4hn$1...@news.lcv.ne.jp> で
furut...@ma2.justnet.ne.jpさんは書きました
> 私だったら、こんな方法使いますよ。
> プログラムの所々でログ取らないと、どこで、ミスしてるかわからなくなりますが。
> あと、結構いろいろテストして、各部分をチェックすると、ほぼ確実です。
(略)
この方法だと、free したポインタの値が malloc で再利用される(可能性が
ある)ので、ポインタの値を見ても、malloc と free の対応がつけられません。
あと、どこで malloc / free したのかわかりませんから、私だったら、
void * deb_malloc(size_t s, char *file, int line);
{
void *pv;
pv = malloc(s);
//ここでファイルにログを取る。
return(pv);
}
void deb_free(void *pv, char *file, int line)
{
// free(pv); デバッグ中は free しない
//ここでファイルにログを取る。
}
#define malloc(s) deb_malloc((s), __FILE__, __LINE__)
#define free(p) deb_free((p), __FILE__, __LINE__)
とします。盛大にメモリリークを起こしますが、まあデバッグ中はしかたな
いでしょう…
PROJECT TEAM DoGA 高津正道 ta...@doga.co.jp
TBD0...@nifty.ne.jp
PROJECT TEAM DoGAのホームページ → http://www.doga.co.jp/ptdoga/
2月20日(日) 今日のマーフィーの法則 [ハロウィッツの法則]
ラジオのスイッチを入れると、大好きな曲のエンディングをやっている。
ではなくて「ANSI Cの範囲しか考えていない」です。で、
ANSI Cの範囲なら、少なくともメモリー管理については
そういう仕様を想定して問題ないはずです。
非ANSI Cの環境まで含めて考えるなら「malloc()したも
のはfree()すれば解放される」ということすら保証でき
ませんから(ひょっとしたらクリーンアップのために何
か別の関数を呼ぶ必要があるかも)、そもそも「free()
すべきだ」だけでは不足でしょう。
> 組込み用の OS 等で
> は、「ヒープの管理は全部アプリケーション側でやってね。」と言うスタンスのもの
> は少なくないですよ。
そういうヒープ管理にmalloc()/free()という名前がつ
いているとしたら不幸なことです。
ええと、だから何だとおっしゃるのでしょう?
ANSI Cのmalloc()/free()の仕様は、その保証がなくて
もかまわないようにできていますが...。
> malloc() したものを free() し忘れることは、malloc()/free() の実装を知るこ
> とより重要でしょう。だから、初心者には malloc() したものは常に free() すべき
> と教えるべきです。
それはもちろんです。いらなくなった時点でfree()する
ことはきわめて重要です。で、いらなくなるのが終了時
であれば、その場合は終了すれば自動的にfree()される
のでfree()は不要だ、と教えるということです。
いずれにしても、どんなものをmalloc()していてそのう
ちどれをfree()したかをプログラマーはつねに把握して
おくべきですね。
でもANSI Cの仕様には「free()しなければならない」と
は書いてありませんよ。書かれていないことまで要求さ
れるのなら「動作が同じ」とはいえないのでは?
なぜ陽に保証されていなければならないのでしょう?
ANSI Cはプログラムを書く側からみた動作を規定する仕
様規格ですから、それを実現するためにシステム側で実
装しなければならない仕様については、暗黙のうちに定
められていればじゅうぶんだと思いますが。
つまり、
> (E) ANSI Cの規格で、上記の前提に基づいてmalloc()/free()インターフェース
> は実装されなければならない、という条件を提示している。
暗黙のうちにこれは示されているだろうということです。
ANSI C。
free()は値を返さないと書いてあります。
解放されたかどうかプログラム側から確認できない仕様
になっているということは、確認しなくてかまわないと
いうことと表裏一体でしょう。
とかいって、最初の記事で私は「それは言語仕様の問題
ではなくてOSの問題です」とか書いてましたね。(^_^;)
「言語仕様(ANSI C)の問題」に訂正しておきます。平に
ご容赦を。(_ _;)
なるほど、これは「malloc()/free()が直接OSのメモリ
ー割り当て/解放のシステムコールを呼んでいるが、そ
れでも終了時にfree()しなくても大丈夫な例」だったの
ですね。了解です。失礼しました。
「立ち打ち」→「太刀打ち」でした。(_ _;)
# えらそうに後神さんの「尊守」を指摘しておきながら、
# 自分でこんなことをしていてはいけませんね。(^_^;)
# 後神さんごめん。
記事 <88ousv$rdt$1...@maha2.doga.higashiyodogawa.osaka.jp> で
私は書きました
> void * deb_malloc(size_t s, char *file, int line);
> {
> void *pv;
> pv = malloc(s);
> //ここでファイルにログを取る。
> return(pv);
> }
> void deb_free(void *pv, char *file, int line)
> {
> // free(pv); デバッグ中は free しない
> //ここでファイルにログを取る。
> }
> #define malloc(s) deb_malloc((s), __FILE__, __LINE__)
> #define free(p) deb_free((p), __FILE__, __LINE__)
> とします。盛大にメモリリークを起こしますが、まあデバッグ中はしかたな
> いでしょう…
私の書いた上記プログラム(というかライブラリ)では、malloc で確保した
領域を開放しないままプログラムを終了させても問題ない、と仮定しています。
今回のスレッドでの議論に沿って考えると、私は deb_free 内で free す
べきポインタリストを保持して(atexitなどで)終了時にちゃんと free する
べきなのでしょうか?… そんなことをするのは単なるCPU時間の無駄以外の
何者でも無いと私は思います。
記事 <88p1v8$7ch$1...@news.lcv.ne.jp> で
furut...@ma2.justnet.ne.jpさんは書きました
> それについては大丈夫です。
> mallocしたあとfreeで解放されるまでは、少なくとも、mallocで確保されることはありま
> せんから、順番でわかります。
デバッグ中ということは、malloc と free が対になるかどうかも疑わしい
んじゃないでしょうか。
たとえば、ログ中に
malloc: ptr=0xABCDABCD
free: ptr=0xABCDABCD
malloc: ptr=0xABCDABCD
free: ptr=0xABCDABCD
free: ptr=0xABCDABCD
となっていた場合、1つ目と2つ目のどちらの malloc で確保したポインタを
二重に free してしまっているのがわかりません。
私もこういうデバッグライブラリを使うことがありますが、その時は、
free し忘れのチェックもありますが、重複 free のチェックの意味も大き
いです。
In article <38AFBC4E...@anet.ne.jp> ,
ロキシー<nas...@anet.ne.jp> writes
># 個人的には、秒単位のパフォーマンスの向上に血眼になるプログラムでない限り
># free()する派、かな。
これは、constant order と最低 linear order を要求するアルゴ
リズムを区別する問題です。これを理解していないプログラマは、
プログラムを書いてはいけないと思います。
秒単位? まぁ、今の人は512MBのメモリを使い切ったことがないの
かも知れませんが、Gbyte単位で細かくmalloc()したものを一つ一
つfree()したら何が起こるか体験してみるのもいいんじゃないかな。
free() で、奇妙な遅れがでるのは、そんなに不思議なことではあ
りません。performace test をしたことがある人なら一度は見たこ
とあるんじゃない?
>(1) free()の必要性はOSに依存する。
>(2) 一律にfree()しておけば、どのOSで動く処理系にも対処できる。
>が、回答として正しいと思います。
exit()とfree()の対応は、どの場合でも一意だと思いますね。例え、
real-time OS だろうと、exit()とfree()を実装するなら、そのよ
うに作るのが常識でしょう。でなければ、いったい何が exit()
なんだかわからん...
In article <88opnf$3to$6...@newsjp.mbn.or.jp>, 電子のお針箱writes:
> この意見は正しいですが、検証できないから free() しなくても良いと言う訳では
> ないですよね。
検証できないなら(つまり、そのポインタを2度と使わないことを保
証できないなら) free() すべきではありません。あったりまえだ。
> それをコンパイラに保証させるために、コンストラクタ/デストラクタがあるので
> す。でも、まだ心配だから机上デバック、長時間連続稼動試験、市販のメモリー
> チェッカツールなんかでやるのが普通でしょ。
そんなことしなくても、別プロセスにして、exit() してやれば、
ずーっと安心できます。何せ、この場合はOS相対で証明されている
わけだから。
> GC なんて使えない状況と言うものを知らないのでしょうか ?
もし、あなたが real-time OS を使っていて、どうしても dynamic
memory allocation が必要になったらどうするんですか? 僕だったら、
reference count なりで GC しますね。もし、malloc()/free()
pattern が前もって決まっているなら、それは dynamic とは
呼びませんから。reference count は実用的なGCです。万能では
ないけどね。dynamic memory allocation で GC が不要な例は、
exit() だけです。他には存在しません。
でも、もし、reference count で、必ず free() することを
要求したら... それは、free() するたびに swap-in のrisk
を負うことになります。memory allocation だけに、これを
簡単に考えるべきではありません。もしかすると数G byte
かも知れないんだから。それよりは、free() せずに exit()
した方が、安全かつ高速です。
> > という手法があって、malloc -> exit っていうのは、そういう安全サイド
> > の手法の一つだと指摘したいな。
> そう言う手法に加えて、アプリケーション側でもできるだけ手当てするのが普通で
> す。
もし猿が、全部、まじめに free() していたら、その努力はパー
です。
---
Shinji KONO @ Information Engineering, University of the Ryukyus
河野真治 @ 琉球大学工学部情報工学科
Shinji Kono wrote:
> > 変数が代入されるfree()だったら、実行時でないとfree()が必要かどうか
> >わかりません。
>
> それはその通りでしょう。で、exit()の前は不必要とわかるはずです。
exit()のって、コンパイラにソースを逆トレースさせるんですか? 条件
分岐があったら終わりやな。
> でも後神さんは、
>
> if(XXX_error()) {
> free_all(free_memory_list);
> exit();
> }
>
> みたいなコードを本当に書いているんですか?
いえ、少なくとも、なにかのエラーが検出されただけで、いきなりexit()
するようなプログラムは(仕事では)書きません。
> だとすると、例の「保護命令違反」とかにはどうやって対処するのでしょう?
> singalで trap して、free_all() しますか? 僕だったら、しない..
例の「保護命令違反」っていったいナニでしゅか?
「メモリ一般保護エラー」は、アクセスが許可されてない領域(Windows95
/98ではシステム領域であったり、メモリがアロケートされてない領域)にプロ
グラムがアクセスしようとした場合に発生します。 プログラムにバグがなけ
れば起こりえない種類のエラーです。
> > また、メモリブロック内を全く参照しないで、free()だけ行なう処理で、
> >どうして巨大なメモリを swap-in するはめになるのでしょうか? 通常、
> >メモリの解放は、メモリ管理テーブルの書き変えのみで、そのメモリ領域
> >にはアクセスしませんから、スワップが発生するとは思えません。
>
> duplicate free() をチェックするような場合は、free()の時にmemory
> header をいじる場合が普通でしょうから触ってしまうでしょう。
> まったく触らない場合もあるとは思います。でも、前のクロスリファレンス
> のような場合や、Mark and sweep するなら、swapからは逃げられません。
mallocで割り当てて返すメモリと、メモリ管理テーブルを分離してあれば、
メモリ領域にアクセスせずに解放できるので、スワップは起こらないでし
ょう。 少なくとも、mallocが最初のテーブルとしてmalloc専用の変数領域
は存在するはずですから、それを管理テーブル専用としてしまうことに何ら
不都合はありません。
> > んで、そのスタックは何メガバイト程度の記憶領域があるんでしょうか?
>
> おお、例のMSDOSだと数百バイトしかないってやつですか? alloca とか
> じゃなくて、自前で用意するのが普通かな?
新種のギャグでしょうか? MS-DOSのスタック領域は、EXEヘッダに必要
サイズが埋めこまれており、ロード時に要求に応じて各プログラム毎に割り
当てられます。 もちろん、中には数百バイトしか必要としないものもある
かもしれません。 基本的に、プログラムを作成した時、プログラマがリン
カに指示して決定します。
そもそも、MS-DOSのスタック領域が最大64KBなのは、i8086のアーキテク
チャからくる制約です。 どんなOSであれ、インプリメントするCPUの制約
を越えることはできません。
なんか、いい加減疲れてきたし、来週は出張なんで、3月以降もこのスレ
ッドが続いてて、気が向いたら投稿します。
+---------------------------------------------------------------------+
| From : Dairyo Gokan ( 後神 大陵 ) |
| Org. : Hitmark Computer Corporation ( ヒットマークコンピュータ ) |
| Adrs : 13256 Northup Way Suite 3, Bellevue WA 98005 |
| TEL:425-649-8808 FAX:425-649-9001 mailto:na...@can.bekkoame.ne.jp |
+---------------------------------------------------------------------+
> (C) ANSI Cとして、free()はOSにメモリーを返す関数で
> はなく、malloc()/free()インターフェースにメモ
> リーを返す関数であることが明記されている
>
> が示せればそれでかまわないでしょう。
>
> 最新のANSI Cは見ていないのですが、ANSI C標準草案で
> は「free()は渡された領域をdeallocateする、すなわち、
> 以降のmalloc()でその領域が再利用されるようにする」
> といった文面になっていたはずです。deallocateの意味
> が念を押してこのように記述されているからには、(C)
> が示されているとみてよいでしょう。
ですから(C)の文章は
free()は、malloc()で取得した領域をOSに返す関数ではない。
故に、OSにメモリを返す目的でプログラム終了時にfree()を呼び出す
必要はない。
という命題の根拠にはなりますが、<88i766$b01$1...@ns.src.ricoh.co.jp>で
理由としている
malloc()で取得されるヒープ領域は、プロセス終了時にOSによって回収
されるメモリ空間に含まれている。
故に、OSにメモリを返す目的でプログラム終了時にfree()を呼び出す
必要はない。
の、「直接の」理由にはならないでしょう。
なぜならば、これを理由とするためには
> このような仕様のメモリー割り当て/解放インタフェー
> スがまともに使えるためには、プロセス終了時にこのイ
> ンターフェースがかかえているメモリーが、何らかのメ
> カニズムで確実にOSに返却されることを暗黙のうちに保
> 証する必要があるからです。
という前提が明示的に保証されていなければならないからです。
逆に言えば、(C)を根拠としたいのであれば、順序としてまず先に上記の前提が
保証されていることを示すのが先でしょう。
例えば、今思いつくのは
(D) すべてのOS上の処理系で実装されていることが保証されている
もしくは
(E) ANSI Cの規格で、上記の前提に基づいてmalloc()/free()インターフェース
は実装されなければならない、という条件を提示している。
くらいですが、他にもあるかもしれません。
--
ロキシー
> 記事 <88orp7$4hn$1...@news.lcv.ne.jp> で
> furut...@ma2.justnet.ne.jpさんは書きました
> > 私だったら、こんな方法使いますよ。
> > プログラムの所々でログ取らないと、どこで、ミスしてるかわからなくなりますが。
> > あと、結構いろいろテストして、各部分をチェックすると、ほぼ確実です。
> (略)
>
> この方法だと、free したポインタの値が malloc で再利用される(可能性が
> ある)ので、ポインタの値を見ても、malloc と free の対応がつけられません。
> あと、どこで malloc / free したのかわかりませんから、私だったら、
それについては大丈夫です。
mallocしたあとfreeで解放されるまでは、少なくとも、mallocで確保されることはありま
せんから、順番でわかります。
このコードは、基本的なコードのみ書いたため、このままでは、分割されたソースに対し
て使えませんです。
なので、ライブラリにでもして、ヘッダーも作ると便利だと思います。
> > 河野 真治@琉球大情報工学です。
>
> > まぁねぇ。でも、malloc()したらfree()すればいいじゃん。ってのは、
> > 本当は、そんなに簡単じゃないよ。
>
> 常に、malloc()/free() が対にできるとは言いませんが、ほとんどの場合可能だと
> 思います。どう言う場合に、難しいのでしょうか ?
グラフ構造を扱う場合(GUIを使ったプログラムなら普通に出て来ます)。つま
り木構造に似ているが、ノードが共有されたり、子が親や先祖を指したりする
ことがありうる場合です。
> > 実際、いつも(malloc() したならば、いつか free())
> > ってのをGC抜きに検証しようと思ったら、一般的には不可能です。
>
> この意見は正しいですが、検証できないから free() しなくても良いと言う訳では
> ないですよね。
場合によってはfree()しなくて良いし、しない方が良いこともありますよ。
例えば、上述のグラフ構造がプログラム終了までほとんど不要にならない場合。
> > (本当のプログラマは、それをどうやって保証しているのだろう?
> > 自分で reference countするってのが C++ では多いんじゃないか
> > なぁ)
>
> それをコンパイラに保証させるために、コンストラクタ/デストラクタがあるので
> す。でも、まだ心配だから机上デバック、長時間連続稼動試験、市販のメモリー
> チェッカツールなんかでやるのが普通でしょ。
コンパイラでは不可能です。あるメモリブロックを指すポインタがいつまで生
きてるかは決定不能ですから。市販のメモリチェッカツールで、ポインタのグ
ラフ構造をたどって、まだ参照されてるかどうか教えてくれる物があるんです
か? (それってGCと呼ぶんだと思う。)
> > それよりも、GCの正当性を証明するほうがやさしかったりします。
> > こっちは、プログラムの振舞ではなくて、データ構造の正当性とし
> > て示せますから。
>
> GC なんて使えない状況と言うものを知らないのでしょうか ?
例えばどういう場合でしょう?
また、そういう状況「も」あるかも知れませんが、それでどういうことを主張
なさっているのでしょう?
前田敦司
> free() の仕様はあくまでも、malloc() した領域を開放するための関数ですよ。多
> くの実装が、解放した領域を領域を OS に返さないようになっているからと言って、
> free() した領域がいつまでもプロセスが所有していると言う保証はありません。実
> 際、VC++ 4.0 のヘルプでは、free() すると OS にメモリーを返すこともあると書い
> ています。(WindowsNT のみですけどね。)
おっしゃるとおりfree()の実装によってどこまで戻すか(OSに返すか、プロセ
ス内で保持したままか)が異なります。
ですから、太田さんのおっしゃったとおり、malloc()がOSからメモリを持って
来るというのは(OSと呼べるものがある環境なら)常に正しいですが、free()は
「その逆の、OSにメモリを返却する関数」とは言えない(実装による)でしょう?
> > malloc()したものは無条件にfree()すべきだと教えるこ
> > とは、その非対称性に気づくチャンスを奪うことにもつ
> > ながりますよね。
>
> malloc() したものを free() し忘れることは、malloc()/free() の実装を知るこ
> とより重要でしょう。だから、初心者には malloc() したものは常に free() すべき
> と教えるべきです。
そういう教え方だと、「free()するとOSにメモリが返却される」という(一般
的には正しくない)考えを植え付けてしまいませんか。(このグループでもそう
思ってらした方がいたみたいです。)
> 実装を知ってより効率の良いプログラムを書くのはその後で良いと思います。
私自身は、ちょっと河野さんとスタンスが違っていて、「exit()前のfree()は
すべきでない」とまでは思いません。場合によってはして良い時もあると思う。
しかし、「exit()前だろうと何だろうと必ずfree()すべき」という単純な考え
方には反対です。
前田敦司
いや、僕の聞いているのは別に確認できるかどうかということを
聞いているんじゃないんですけど…
確認しなくてかまわない環境のためのインターフェースであるということが、
何らかの文章として明記されているかどうか、と尋ねているんですよ。
In article <pyp1z67...@tp560e.sowa.is.uec.ac.jp> MAEDA Atusi <ma...@is.uec.ac.jp> writes:
| きてるかは決定不能ですから。市販のメモリチェッカツールで、ポインタのグ
| ラフ構造をたどって、まだ参照されてるかどうか教えてくれる物があるんです
| か? (それってGCと呼ぶんだと思う。)
Sun WorkShop 5.0以降に含まれるデバッガdbxの実行時検査機能(RTC)では、メ
モリスキャンを行ってメモリリークの検査を行うとおもわれます。なぜなら
「ブロックの先頭を指すポインタが検知されず、ブロックの内部を指している
ポインタが見つかった場合」や「割り当てられているブロックへの唯一の参照
は、レジスタ内に含まれています」といった場合にエラー・警告メッセージが
表示されるからです。
http://docs.sun.com/ab2/coll.442.1/SWKSHPDEBUG/@Ab2PageView/9207?Ab2Lang=ja&Ab2Enc=euc-jp
| か? (それってGCと呼ぶんだと思う。)
ちなみにメモリスキャンがコンサバなのかaccurate(exact)なのかがドキュメ
ントを見ても特に書いてなかったので分かりませんでした。特に書いてないっ
てことはaccurateなのかなあ。でもそれって既存ライブラリバイナリを考えた
ときに可能なのだろうか。
あと上のURLにはこんな記述もありました。
> 解放されていないブロックを「メモリーリーク」と呼ぶこともあります。ただ
> し、この定義はあまり使用されません。プログラムが短時間で終了する場合で
> も、通常のプログラミングではメモリーを解放しないからです。プログラムに
> そのブロックに対するポインタがある場合、RTC はそのようなブロックはメモ
> リーリークとして報告しません。
--
§NTTS○FT 技術開発部エレクトロニックコマース技術センター 上原 潤二 §
PGP Key fingerprint = B7 C0 CB 1F 1C 88 69 2A 25 36 8A EE 93 A3 61 72
片山@PFUさん、こんにちは。
> #スレッドが大きくて、どの記事にフォローするか迷ったのですが、、、
ほんとでかいスレッドになっていてチョットこまっています(^○^)。
> 確かに規格では規定されていませんが、プログラム終了時に解放される
> と考えてよいでしょう。少なくとも、マットウな OS なら、そうなるは
> ずです。でなければ、プログラムを強制終了させられないことになりま
> す。
>
> #もちろん、freestanding environment は考えていません
> #そもそも、malloc()/free() が定義されてないのですから
そのとうりですね、でも、実際malloc()/free()は一筋縄では解決できません
(^○^)。多分使用している環境やアプリがその使用方法や正確を変えてしまいます。
OSが仮想メモリーをどう扱っているかアプリにとって十分な容量とスピードがあるか
などにもよりますし(^_-)。
> >// 割り当て
> > assert(pT); // 多重割り当ては許しません
>
> これでは、pT が NULL(メモリーが割り当てられていない時)にメッセー
> ジが出ますけど、、、
すいませんassertの論理を間違えちゃいました(^_^;)。free(NULL)が許されてい
る事は知っています、
重要な事は「開放したらポインタをNULLにセットする」事で不正なアクセスが起きた
事を分かりやすくする事です。
Junn Ohta wrote:
> 元記事の方は、そのようなmalloc()の使いかたをしてい
> るときに使い終わったメモリーをfree()しなくてよいか
> とお尋ねなのではないでしょう。
>
> むしろ、そのようなプログラムが長々と稼働したあとで
> 仕事を終えて終了する直前に、それまで確保していたこ
> まごまとしたメモリーをすべての個別に解放することが
> 本質的に必要なのかをお尋ねなのだと思います。
>
おっしゃる通りです。「もう使わないなら」と元記事に書いてある
ように、使い回しうんぬんという話と違って、原理的に
メモリーリークになるかどうかという問題です。
結論としてはならないという事で解決ですね。
逆に言えばメモリーリークを意図的に起こさせるには
どうするのでしょうか。意図的にハングアップさせて
強制終了とかWindowsのMMFとかでなく、単にmalloc
を使うだけで正常に終了している限りメモリーリーク
を起こすことはないはずだというのが皆様の議論の
主旨のようですので。
Arita
なぜそうお尋ねなのか理解できません。明文化されてい
ることが重要なのですか?
fj.os.ms-windows.programmingで"exeを小さくするには?"という話題が出てま
すが,
昔MSJ(MicrosoftJournal)かなんかで、ライブラリをそういう実装の自作のもの(
同機能のWinAPIのラッパー)と置きかえる、ってのがありました
--
BERO
Console/Emulator Programming
http://www.geocities.co.jp/Playtown/2004/
be...@geocities.co.jp
>> >いろいろOSの事なども、出ていますが、C言語の特徴の高い移植性を生かすために
>は、
>> >free()でメモリは解放すべきでしょう。
>>
>> では、exit() もしないことですね。
><中略>
>やはりUNIXに依存しているじゃありませんか。
exit() は標準ライブラリ関数ですよ。
--
片山@PFU
もしかして、組み込み環境のような環境では使えないも
のであることが規格か何かできちんと明記されているか、
とお尋ねだったのでしょうか?
そういうことなら、ANSI Cには「すべてのライブラリー
関数はhosted environmentに対して定義される。free-
standing environmentでは実装定義となる」という意味
のことが書かれています。hosted environmentはargcや
argvの受け渡しなどいくつか従わなければならない制約
があるので、ANSI C仕様が組み込み環境のためのもので
ないことは明記されていると考えてよいと思います。
これでは不足ですか?
>例の共有メモリを使うタイプだったら、freeを使わないと、大変ですから、一応書いてお
>くべきだと思います。
本当に、そのような実装があるのでしょうか。それは、どのような OS、
処理系でしょうか。一つで構いませんから、実例を教えて下さい。
--
片山@PFU
>ですよね。malloc/freeの場合、ライブラリで管理してる使用中の領域をOSに
>返すルーチンをatexit()で登録しとけばいいわけですから...
そういう実装ではまずいでしょう。例えば、abort() を安心して呼出す
ことが出来なくなります。
>ふつー誰が書いてもexit()時に返却されますよね。
exit() せずに終了しても大丈夫なように実装するする必要があります。
プログラムが終了した後のことは C の規格の範疇ではありませんから、
そうなっていなくても規格に準拠していないとは言えないでしょうけど、
実用的な処理系にはならないでしょう。
#この記事も freestanding environment については述べていません
--
片山@PFU
そうですね。いままで出た情報をまとめると、malloc()
したメモリーをfree()せずに終了した場合、
(a) UNIX、MS-DOS、Windows95/98/NTならメモリーリー
クは起きない
(b) ANSI Cならメモリーリークは起きない
(c) (malloc()/free()という関数仕様から)まともなOS
とまともな言語処理系の組み合わせならメモリーリ
ークは起きないと期待してよい
(d) 上記のいずれでもない環境ではメモリーリークを起
こす可能性がある(しかしfree()したからといって
メモリーリークが起きないとは保証できない)
といったところでしょうか。
> 逆に言えばメモリーリークを意図的に起こさせるには
> どうするのでしょうか。
飯嶋さんの
<38AFB2D7...@mail.ecc.u-tokyo.ac.jp>
によれば、
WindowsのWin16 APIでGlobalAlloc/GlobalFreeを使い、
GlobalFreeを呼び忘れた場合
があるようです。ただしmalloc()/free()がこのAPIを直
接呼び出すようなコードを生成する処理系があるかどう
かは不明です。
また、右松さんの
<88jtrm$898$1...@pooh.isoternet.org>
によれば、
malloc()相当のものが共有メモリーの割り当てと等価
になっているOSがある
そうで、この環境でfree()相当の関数を呼び忘れるとメ
モリーリークを起こす可能性があります。ただし右松さ
んの記事にはメモリーリークが起きると書かれているわ
けではありません。また、用意されている関数はmalloc
()/free()ではない可能性があります。
電子のお針箱さんの
<88opnc$3to$3...@newsjp.mbn.or.jp>
によれば、
組み込み用のOSでは「ヒープの管理は全部アプリケー
ション側でやってね」と言うスタンスのものが少なく
ない
そうです。この環境でfree()相当の関数を呼び忘れると
メモリーリークが起きそうです。これも用意されている
関数はmalloc()/free()ではない可能性があります。ま
た、このような環境ではmalloc()/free()がANSI C仕様
に準拠している可能性はなさそうです。
さらに、古田さんの
<88nccc$ipm$1...@news.lcv.ne.jp>
によれば、
「freeを使わないと、トラブルを起こすシステムは、
現にあります」
だそうで、この「トラブル」もメモリーリークを指して
いると思われます。ただし古田さんは具体的にどのシス
テムでそうなるのかは示していません。べつのところで
WindowsのHeapAllocをmalloc()という名前で呼び出して
いるアプリケーションがあるとお書きでしたが、これは
free()しなくても問題が起きないそうなので、上とは関
係ないようです。
あと、いくつかの記事でWindowsのリソ-スリークの話
が出てきましたが、メモリーリークとは関係なさそうな
ので省略します。
というわけで、まだ
・メモリー割り当て/解放にmalloc()とfree()を使う
・malloc()で割り当てたメモリーをfree()で解放せずに
終了するとメモリーリークになる
実例はひとつも示されていません。
# 「freeを使わないと、トラブルを起こすシステムは、
# 現にあります」とお書きになった古田さんが実例をお
# 示しにならないのは、ずいぶん奇妙な話ですけどね。
> となっていた場合、1つ目と2つ目のどちらの malloc で確保したポインタを
> 二重に free してしまっているのがわかりません。
>
> 私もこういうデバッグライブラリを使うことがありますが、その時は、
> free し忘れのチェックもありますが、重複 free のチェックの意味も大き
> いです。
それはありますね。
また、メモリ確保だけのログでは、どこがおかしいかはわからないので、位置を特定する
には、他の所でもログを取らなくてはなりません。
> > とします。盛大にメモリリークを起こしますが、まあデバッグ中はしかたな
> > いでしょう…
>
> 私の書いた上記プログラム(というかライブラリ)では、malloc で確保した
> 領域を開放しないままプログラムを終了させても問題ない、と仮定しています。
人の環境では、どうなるかわかりませんが、自分の環境なら大丈夫な事がわかってますか
らね。
でも、1つ問題がありました。
メモリ不足の危険があることです。
ふつう大丈夫ですが。
> 今回のスレッドでの議論に沿って考えると、私は deb_free 内で free す
> べきポインタリストを保持して(atexitなどで)終了時にちゃんと free する
> べきなのでしょうか?… そんなことをするのは単なるCPU時間の無駄以外の
> 何者でも無いと私は思います。
公開時には、取り去ってしまうので、freeしなくても十分だと思います。