nodocumentsの日記: これだけはわかった 15
日記 by
nodocuments
表のトピック科学者は研究に使っているコードを公開すべき?を読んで、これだけはわかった。
『メモリリークはプログラマにとって不倶戴天の怨敵である』
でも、バッファオーバーランやアドレスエラーまで区別なくメモリリークと呼んでいるような気がして、変な感じ。
許容できない順に示すと、
アドレスエラー>=バッファオーバーラン>>>>>メモリリーク
だと思うんだがな。
マシンのリソースが許す限りは、メモリリークは動作に支障ないし。
支障があると思ってるなら、それはたぶん、実はアドレスエラー。
GCのない言語(C/C++)を使っといて (スコア:0)
メモリリークを嫌がるって馬鹿なの? マゾなの? ツンデレなの? と思わざるをえない。
Re:GCのない言語(C/C++)を使っといて (スコア:1)
君はOSなし環境でもGCのある言語を使うつもりかね?
それは過去に実績がある (スコア:1)
lisp machine...
fjの教祖様
Re: (スコア:0)
別にGCはOSの専売特許じゃないから問題あるまい。
OSも載らない貧弱な環境でGCが使いモンになるかと言いたいならその通りかもしれんけど。
象徴なんだよね (スコア:0)
メモリリークに限らず、「プログラマがコントロールできていない部分」の。
その中でも「実害はたいした事なくてもキモイ」から選ばれてる感じ。
心構えとして、些細なミスも許しません!というか。
# 実際、そのぐらいの心構えでいいと思うよ。
# 製品ならリークの試験もするっしょ。
それはそうなんですけどね、違うんですよ (スコア:1)
そのとおりです。
ただ、「アドレスエラー」が起こっているとか「バッファオーバーラン」が起こっているときというのは、ほぼ100%確実にメモリリークも起こっています。逆にアドレスエラーやバッファオーバーランを起こさずに、メモリリークを起こし、なおかつそれが意図的ではない などというのは、奇跡にも等しいのです。
結局メモリリークと言うのは「どこかでメモリを確保して」「それを解放し忘れた」って事ですよね?で、メモリを確保したら、確保したメモリのアドレスを憶えておくものです。で、確保したアドレスを起点に一連の操作を行い、最後にメモリを解放する、と言うのが流れのはずです。
メモリを解放し忘れる、というのは大抵この「確保したアドレス」をベースにした一連の流れを記述している最中に、プログラマが何をやっているのか判らなくなっている事を表すんですよ。大抵の場合、デザインを紙に書かずに頭の中で処理している最中に、何らかの形で集中力を阻害されるイベントが発生し、頭の中が混乱して発生します。結果としてほぼ確実に
バッファオーバーラン ⊇ アドレスエラー ⊇⊇⊇⊇⊇ メモリリーク
となっているものなんです。
メモリリークは他のバグと独立事象として発生するバグじゃない。これがメモリリークが憎まれる理由なんです。
fjの教祖様
Re:それはそうなんですけどね、違うんですよ (スコア:1)
そうかなぁ。
その通りだったら、どうして使用済みメモリが自動的にコレクトされるような言語が発達してきたんですか?
ワーク領域の確保は人間が目指す目的のための手段だけど、解放は機械の都合でしかないからでしょ。
不純物ですよ、こんなの。
機械の都合に斟酌してないからといって集中力が切れたはずだとか、混乱しているとする考えには同意できません。
メモリリークなんて、リソース飛ばさない限りはチューニングの範疇。
そして、チューニングなしに目的が達成できるならしなくていいこと。
#商業プログラマとして納品物を作る場合には適用できない価値観という認識はもちろんあります
Re:それはそうなんですけどね、違うんですよ (スコア:1)
あぁ、なにかGCの基本を勘違いしていますね。
「使用済みメモリを自動回収する」言語は存在しますが、ユーザーがもう使いたくないなぁと思ったメモリ領域を自動的に使用済みとして認識してくれる言語はひとつも存在しません。リンクから外したりして、「もう使わない」事を明示するのはあくまでもプログラマのお仕事。
逆にGCがあってもメモリはリークするのですよ。何か適当なリンクリストに貼りつけて外すのを忘れれば良い(実際3ヶ月前にJVM回りのバグとして苦しめられたのはそういうバグ)。
リンクから外した後、メモリを解放する際に行うべき処理を事前に登録することで、実際に「ぽいっ」とやったときにそれが自動的に実施される、という記述を可能にしている言語も「まさにそこを記述し間違えれば」同じことです。
GCは貴方が思うのと違って、メモリリークを回避する能力なんぞ全くありません。GCの有能性はむしろ、「すでに解放したハズのメモリを多重に解放する」のを阻止するところにあります。それによってメモリ管理機構自体が破綻するのを抑える事ができる。
.
あとは GC というよりは「コンパクション」の仕事ですが。メモリの利用状況がフラグメンテーションを起こして cache ヒット率などが悪化している状況を、コンパクションは改善してくれます。そういう形で役に立つことはあります。
GCこそ、「チューニング」の範疇なのですよ。
fjの教祖様
Re:それはそうなんですけどね、違うんですよ (スコア:1)
言語がどういう方向性で発達してきたか、です。GCがどんな機能か、じゃありません。
う、あるいは思わないといけないことがすでに不純物。
使ったら、忘れる。拾われようが拾われまいが、知ったことではない。
Re:それはそうなんですけどね、違うんですよ (スコア:1)
たった9文字で、君は本質を不純物と間違っている事をはっきりと示している。
まず「使ったら」と書いているが、これは「使い終わったら」の間違いだ。使っている最中に忘れたら酷い事になる点は同意するだろう。
で、いつが使い終わったポイントなのかね?
使い終わったポイントを常に、正確に、記述出来るのであれば、そこでメモリ開放コードを入れれば良いだけなのだから、メモリリークなど(機構的に自動化されていようがいまいが)バグとして発生するわけがないし、あってもせいぜいケアレスミス以上のものにはなりえない、というのは理解出来るね?
しかし。今、君がリンクリストから解放したそのポインタの先にあるチャンク。本当に今解放してよかったのかね?! 本当に、そのタイミングで「これ以上どこからもアクセスできない」状態にしてよかったのかね?!
メモリチャンクの管理は、実はメモリチャンク自体の管理が難しいのではない。「解放するべきポイントがどこなのか」を厳密に正しく規定することの難しさこそが本質なのだ。ここにメモリリークが発生する原因がある。そしてこれ故にGCは「メモリリークに対して」なんら有効な手立てではないのだ。
逆に、この性質ゆえに、メモリリークがあると言う事実はプログラムが他の多くのバグをも内包している事を示している。メモリリークの存在は、ほぼ確実に プログラマがロジックを見失った瞬間があり、その後正しく復旧しなかった 事を示している。Garbage In, Garbage Out なプログラムがそこに存在する兆候そのものなのだ。
fjの教祖様
Re:それはそうなんですけどね、違うんですよ (スコア:1)
何を言いたいのかわからん。
『使ったら忘れる』を『使用中に忘れる』って…そこで揚げ足とれると思われるほど見くびられてるのか?
一生懸命にメモリの解放タイミングは管理すべきと言ってるようだが、メモリ解放は何のために必要だ?
繰り返すが、メモリを確保するのは目的のための手段だ。では解放は何のためだ。
本来なら、そんな機械のためのお作法に注意力を割きたくはないんだ。
そんなのは思考の上の不純物なんだよ。
集中が途切れてる?混乱してる?本来の目的に関係のない、機械のお作法を思い出さなきゃ成らないこと自体が集中力の途絶であり混乱の元だ。
理由はわからないけどしなきゃいけないお作法は、ロジックの一部じゃないんだよ。
Re: (スコア:0)
メモリリークが嫌なのは、
「テストやデバッグが死ぬほどめんどくさい。」
これに尽きます。他のバグにくらべて、すごく時間と手間がかかるんですよね。
>逆にアドレスエラーやバッファオーバーランを起こさずに、メモリリークを起こし、なおかつそれが意図的ではない などというのは、奇跡にも等しいのです。
いや、それ普通だから。
>逆にGCがあってもメモリはリークするのですよ。何か適当なリンクリストに貼りつけて外すのを忘れれば良い
これをメモリリークと呼ぶべきかどうかという問題がまずありますね。
CやC++で恐れられてきたメモリリークとは全く原理が異なるし、なぜメモリリークが
これほどまでに嫌われているのかの理由を誤解させる意味でも、この現象にはメモリ
リークと別の名前を付けた方がいいと思います。
というか、ひょっとしてメモリリークを誤解してません??
メモリリークは「リンクを削除しちゃった」が普通ですよ。
Re:それはそうなんですけどね、違うんですよ (スコア:1)
あぁ、そこも間違っている。それはメモリリークではない。
メモリリークと言うのは「プログラマが管理しているつもりになっている動的メモリの確保状態」と「実際の確保状態」で、実際の確保状態のほうが多い状態を言う。つまり
「削除したつもりになっているメモリが、まだ確保された状態でどこかにある」
これがメモリリーク。
.
「解放するべきチャンクを表すアドレスを捨てちゃってどこにもない」は確かにメモリを解放できなくなる要因ではあるけれど、メモリリークそのものではない。それはダングリング・ポインターの一種で、ロストアドレス という名前がある。この名前がどれぐらいメジャーなのかまでは知らないが。
ロストアドレスは「動的に確保したメモリ」以外に対しても起こる。で、静的に確保してあるアドレスのアドレスをロストしてもメモリリークには繋がらない。なのでこれはメモリリークそのものではないのだ。
GCがロストアドレスのせいでロストしたチャンクを発見し再利用に回してしまったために、バグが発生することが有る。GPGPUのようなものを使う場合、結果が書かれるべきメモリチャンクが演算終了前にGCに回収・再利用されてしまうと、再利用先が使っている最中に突如としてデータが書き換わる、などという現象が起こる。逆に、せっかく演算した結果がロストしてどこにも反映されない、などというケースにもつながる。似たような現象は共有メモリにおいても起こるので、ハードウェアが関与しないと起こらない、と言うわけではないぞ。
ロストアドレスは結果としてメモリリークへと至る。その意味では「メモリリークはロストアドレスの予兆」でもある。で、ロストアドレスは計算結果がおかしなところに書き込まれたり、丸ごと失ってしまったり、と言った現象の予兆でもある。故にメモリリークは、計算結果が信頼できなくなる予兆でもあり、故にメモリリークは放置してはいけないの。
.
「Garbage Collection: Algorithms for Automatic Dynamic Memory Management」 by Richard Jones, Rafael Lins
という本がある。ISBN-13: 978-0471941484。今調べたら ¥ 12,233 …えー、そんなに高かったっけか…1ドル 123円ぐらいの時に買ったはずなのだがもうちょっと安かった気が…900ドルを切ってたと思うんだが…
とにかく。メモリリークが厳密に何なのかとか、GCは正確にはどのような問題から誰を守ってくれるのかとか、真面目に勉強したいならこの本を読むと良い。この辺の話は真面目に英文を読む必要があるので苦痛かと思うが、一旦 GC のやり方に関する話になったら、英語の本としては図が満載でとても楽しい。お勧めだ。
---
ちなみに、さらに調べたらこんな本の予約も受け付けていた:
「Advanced Garbage Collection: Algorithms for Automatic Dynamic Memory Management (Chapman & Hall/Crc Applied Algorithms and Data Structures Series) Richard Jones、Antony Hosking、 Eliot Moss (ハードカバー - 2010/11/15)」
fjの教祖様
Re: (スコア:0)
>「削除したつもりになっているメモリが、まだ確保された状態でどこかにある」
>これがメモリリーク。
みごとなオレオレ定義ですね。感服しました。
リストにメモリの初期化漏れも入れてください (スコア:0)
T/O