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()の実装を示せる人はいら
っしゃいますか?
ひとつの要素を検索して解放するコスト