X



GCは失敗。メモリは自分で管理せよ! その2©2ch.net

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん 転載ダメ©2ch.net
垢版 |
2015/11/18(水) 23:24:59.79ID:BUQ68wTG
GC、ガベージコレクション、ガベージコレクタ、ガーベジコレクション、ガーベジコレクタは使えない。
以下GCと記す

プログラマをメモリ管理から開放する!
といいつつ、メモリリーク問題の文献が大量にある。
これすなわち、メモリリーク問題が全然解決していないということ。
さらに、メモリ解放のタイミングの文献まで大量に生み出した。
これすなわち、新たなるメモリ管理に関する問題を生み出したということ。

malloc、freeじゃないが
結局のところ、メモリを管理するという技術は、今しばらくは、身につける・教える・学ぶべきではないだろうか?
使って、そのまま放置しても、基本的にはGCがなんとかしてくれている。
ランジョブからジョブ終了までさほどの時間を要さない。メモリも大して使わないならいいだろう。
しかし、規模が大きくなり常駐ジョブやメモリ大量使用のジョブになってくると、そんなメモリ管理の方法でやっていると、
上記「文献」を生み出されてしまう。

入門時は、メモリに無頓着でもいいだろう。それよりも、目的を達成することが先決だ。
しかし、慣れてきたら、やはりメモリの管理まで余裕を持って自分で行うべきだろう。

前スレ
GCは失敗。メモリは自分で管理せよ!
http://peace.2ch.net/test/read.cgi/tech/1412986420/
0367デフォルトの名無しさん
垢版 |
2016/01/27(水) 18:38:52.76ID:XmqLFQFE
c#の欠点はデストラクタが呼び出されるタイミングが分からないこと。
不便で仕方ないや。
0368デフォルトの名無しさん
垢版 |
2016/01/27(水) 18:56:08.53ID:VDkVQpP+
最近VB.NETを使い始めたんだけど
new したオブジェクトが不要になった時にDispose()よんだり参照にNothing代入する必要ってない(やってもいいが無意味・無駄)なのかな?
0369デフォルトの名無しさん
垢版 |
2016/01/28(木) 08:05:17.75ID:oip5UtLa
c++のデストラクタは例外投げられないウンコ仕様
だから皆デストラクタ内で発生したエラーは握り潰してる

他の言語はあんなバカなの真似する必要ない
0371デフォルトの名無しさん
垢版 |
2016/01/28(木) 18:02:00.92ID:xwQj4KRs
javaはファイナライザで発生した例外は握りつぶすことが仕様で決まっているな。
c++の場合は、デストラクタでどうしても例外を外に伝えたかったらやりようはある。
0373デフォルトの名無しさん
垢版 |
2016/02/10(水) 11:29:59.19ID:lL2Wg2mH
Javaは強制的に解放させることもできるようにすべきだったな。
0374デフォルトの名無しさん
垢版 |
2016/02/10(水) 11:41:46.63ID:83b7Yxnh
Java(VM)は(すべてのプラットフォームで)強制的に解放させることもできるようにすべきだったな。
0375デフォルトの名無しさん
垢版 |
2016/02/10(水) 12:19:44.29ID:k9iR7lzz
都度メモリ管理するよか、GCに任せた方がスループット的に有利な場合も多いでしょ。
0376デフォルトの名無しさん
垢版 |
2016/02/10(水) 14:29:59.29ID:CcpqYYAq
GCはメモリ管理に関しては成功してる、
でも、メモリブロックをオブジェクトに昇格させたにも関わらず、相変わらず「メモリ管理」だから失敗。
0377デフォルトの名無しさん
垢版 |
2016/02/10(水) 17:29:46.71ID:+sMp0qjD
そうそう、メインメモリの管理に関しては100%成功している
しかし、今やメインメモリはそれほど貴重なものではないわけだがな
コンシューマでも数十GB積んでたりは珍しくない
メインメモリがなくなるより他のリソースが枯渇する方が現実的
だからメインメモリ以外のリソースに関しては使い終わったら即座に開放してほしいから
GCとは別にRAIIを行う仕組みを導入するわけだが
真剣に考えていくと、RAIIはGCと相性が悪い
そもそも使い終わったら自動で即座に開放(RAII)できるなら全てのGCはそう実装すべきで
それが出来ないからわざわざコストのかかるマークスイープを遅延して実行しているわけだからな
C++みたいにGCを参照カウンタ方式にして、プログラマが人力で循環参照が無いことを保証する以外に
あちこちから参照されるオブジェクトのRAIIを自動化する方法は無い
0380デフォルトの名無しさん
垢版 |
2016/02/11(木) 16:22:39.56ID:vxbPXQEr
javaもsandy-bridge以降でSSDとかならそれほど重いってわけじゃないけど
相変わらずatomでeMMCだったりする環境も並行して存在してて
そこで動かすと改めて糞だと思うわけよ
GCが悪いんじゃなくてjavaランタイムが悪いんだろうけどね
0381デフォルトの名無しさん
垢版 |
2016/02/11(木) 19:04:56.18ID:EuRhj+pR
フラッシュとJAVAは、システムに見つかり次第、速攻アンインストールしている
0383デフォルトの名無しさん
垢版 |
2016/02/13(土) 15:34:22.04ID:OKKAbu21
最近のPC環境でも贅沢が過ぎるプログラムは動かん。
最近の奴だと、Node.jsのパッケージマネージャnpmが`npm search`と初回に打つとパッケージ検索用のインデックスを作ろうとするんだけど、
1つのjsonオブジェクトにまとめようとするからかOOMエラーを吐いて失敗するっていう不具合。
npmに登録されてるパッケージ数が膨大になったせいもあるが、設計を間違えると遅いどころか動かなくなる。
0385デフォルトの名無しさん
垢版 |
2016/02/13(土) 23:42:47.95ID:VLo29AwR
リソースを共有した上で最後の参照が切れた時点で回収してほしい
しかし誰が共有するかもその寿命も実行時までわからない
そういう前時代的なダサい設計をした時の話しなんだろ
Loan Patternはこの状況では役に立たない
0386デフォルトの名無しさん
垢版 |
2016/02/14(日) 00:56:38.97ID:mwiD0ozs
しかし、言語側は、そういうダサい設計も許さないといけないので
マークスイープ系GC搭載で、循環参照が有っても良いことが前提になっている言語で
「使い終わったら自動で即座に開放」を実現するのは困難
そんなことが可能なら、マークスイープは要らないからな
0387デフォルトの名無しさん
垢版 |
2016/02/14(日) 19:42:04.72ID:I7Qc+kxz
循環参照なんて放置すればいいの
どうせプロセスが終了すればOSが開放してくれるの
0388デフォルトの名無しさん
垢版 |
2016/02/14(日) 20:10:25.23ID:EqhxGdNa
>>387
Windowsのように定期的に再起動しなければいけないソフトウェアができあがっちゃいそう
0390デフォルトの名無しさん
垢版 |
2016/02/15(月) 19:50:44.55ID:L+A+Kd2h
そこはRustで
0392デフォルトの名無しさん
垢版 |
2016/03/23(水) 02:31:06.32ID:MFzvJNSi
常識的に考えてカーネルの実装にはGCなんて使えないし
業務アプリケーションではパフォーマンスより開発速度がはるかに重要になる
結局適材適所だ
GCを強制されるのは苦痛だが使えないのも苦痛だ
好きな時に使える言語がいいよね!
0393デフォルトの名無しさん
垢版 |
2016/03/23(水) 03:41:39.64ID:SoMbpeP6
パフォーマンスが問題にならないGCが一つだけあって、それが参照カウンタ方式のGC
パフォーマンスが問題にならない→即座に逐一削除できる→RAIIが出来る
非常に強力だがプログラマが循環参照が無いことを保証しなければならない
しかし、循環参照が発生する場合は設計段階で分かるのでそれほど深刻では無いのだ!
0394デフォルトの名無しさん
垢版 |
2016/03/23(水) 03:47:03.14ID:VzK80P8k
androidでもう何も判らん状態でプログラミングして
それなりに動くのができたからおれは許したよ
でもサービスまで勝手に回収されちゃうとは思わなかったわ
アホだろグーグル
0395デフォルトの名無しさん
垢版 |
2016/03/23(水) 07:53:14.58ID:JT2FURwc
RAIIに必要なのはデストラクタが呼ばれることであって実際にメモリが解放されることじゃないから
GC言語でもRAIIができないわけじゃない。
0396デフォルトの名無しさん
垢版 |
2016/03/23(水) 10:07:19.06ID:SB04Y3rp
RAIIに必要なのは適切なタイミングで確実に解放処理が呼ばれることであって
いつ呼ばれるかわからないデストラクタではだめ
0397デフォルトの名無しさん
垢版 |
2016/03/23(水) 18:24:05.29ID:jWiL+V+6
かつてStandard MLの実装で、GCじゃないメモリ管理方法をやってみたのがあったな。
コンパイラが全部自動でやるからコードの見た目はSMLなんだけど、いざ動かすとGCより遅かった。

ある程度プログラマがリソース管理のためのヒントを与えないと、GCを捨てられない。
0398デフォルトの名無しさん
垢版 |
2016/03/23(水) 20:05:29.02ID:JT2FURwc
>>396
おまえが言っているのはファイナライザ。
それと、デストラクタはメモリの解放なんかしないよ。デストラクトするだけ。
0399デフォルトの名無しさん
垢版 |
2016/03/23(水) 21:43:30.89ID:SoMbpeP6
この際、呼び名はどうでも良い
参照カウンタ方式以外のGCでは、どこからも参照されなくなったことが、即座にはわからない
だから、自動で即座に開放関数を呼び出すことが出来ない→RAIIが出来ない

C#で言うところのusingみたいに、プログラマが手動で情報を与えるなら出来る
だが、usingはGCでは無い
0401デフォルトの名無しさん
垢版 |
2016/03/26(土) 05:40:22.28ID:vD3g1idC
>>393
間違い
マークスイープのように負荷が集中しないだけでありパフォーマンスへの影響はある
特にツリー状のデータついてルートが削除された時子要素もデクリメントする必要があるため負荷が大きい
カウンタはオブジェクト毎に持つためコピーオンライトとの相性が悪い
また言語の機能として実装されなければ明示的に行う必要がある(例えばCとか)
そのためgcない言語ではマークスイープと比べ非常に面倒なことになる
0402デフォルトの名無しさん
垢版 |
2016/03/26(土) 10:35:48.15ID:GKwGPSgf
androidで原因不明のフリーズが発生、プロジェクトはデスマーチに突入した
これだからGCは
0404デフォルトの名無しさん
垢版 |
2016/03/26(土) 11:39:40.83ID:MgEq8J/o
>>401
そりゃどんなものだって多少の負荷は有るよ
しかし参照カウンタの上げ下げの負荷なんか
マークスイープに比べれば無いも同然
0405デフォルトの名無しさん
垢版 |
2016/03/26(土) 18:02:09.56ID:2IjmMYr5
マルチスレッド環境だと参照カウンタとかいうクソアルゴリズムは使い物にならない
0409デフォルトの名無しさん
垢版 |
2016/03/26(土) 20:22:44.37ID:QL60ocAy
>>407
確かに現実的にオーバーフローしないと言えると思うけど
STLとかもそういう実装になってる?
0410デフォルトの名無しさん
垢版 |
2016/03/26(土) 20:52:01.21ID:rTAUpSul
使う側は少なくとも1つのポインタを持たなくちゃいけないんだからオーバーフローし得ないだろ
0411デフォルトの名無しさん
垢版 |
2016/03/26(土) 22:10:23.58ID:6zuFQelp
マルチスレッドでGCスレッド立ち上げて、再配置起こる可能性のある普通のGCだと、オブジェクト毎にLock,Unlockできる何らかの機構が必要だし、参照カウンタ増減するより高頻度でその機構使うよね。
0413デフォルトの名無しさん
垢版 |
2016/03/26(土) 23:56:59.65ID:MgEq8J/o
例えばWindowsだとInterlocked系のAPIを使えば
マルチスレッドでも安全に参照カウンタを増減できるから
パフォーマンスは何の問題もない
0414デフォルトの名無しさん
垢版 |
2016/03/27(日) 00:13:33.76ID:MdJCnp0Y
C#なら参照のコピーはただのワード代入で済む
メモリ確保もポインタへの加算だけで済むから圧倒的に速い
回収もマルチスレッドで処理されるから圧縮フェーズ以外はUIへの影響もなくユーザ目線では実質コストゼロ
良いコードを書いてるなら圧縮もたまにしか起こらないし起こっても大した事ない
0415デフォルトの名無しさん
垢版 |
2016/03/27(日) 00:26:17.07ID:vj+h39OC
>>399からの流れを見ればわかるがそういう話ではない
参照カウンタ方式以外のGCは、オブジェクトがどこからも参照されなくなったことが「即座」にわからない
だからRAIIが出来ない、そういう話

もちろん、参照の値が書き換わるたびに毎回マークスイープを実行すれば
即座にゴミが分かるがのでRAII出来るが、マークスイープは重いので参照が書き換わるたびに毎回実行できない
その意味で、循環参照以外のGCは重いと言っている

参照カウンタ方式は軽いので毎回実行できる
即座にゴミが分かるからRAIIが出来る

参照カウンタ方式で問題になるのは循環参照が起こった場合だが
循環参照が発生する箇所は設計段階で分かるので、実際には大した問題ではない
C++であれば、片方をweak_ptrにすればよいというだけの話
そこさえ気を付ければ、参照カウンタ方式とデストラクタの組み合わせは非常にうまく機能する
IDisposableのようなものも要らない
0416デフォルトの名無しさん
垢版 |
2016/03/27(日) 00:27:10.73ID:vj+h39OC
>循環参照以外のGCは重いと言っている

↑間違えた

参照カウンタ方式以外のGCは重いと言っている
0417デフォルトの名無しさん
垢版 |
2016/03/27(日) 00:41:23.52ID:15KjVKPo
>>413
安全が何で保証されてるのかを知るためにアセンブラを勉強しなさい。
その上で「パフォーマンスは何の問題もない」かどうかを語りなさい。
0418デフォルトの名無しさん
垢版 |
2016/03/27(日) 00:59:17.81ID:kBj57j3O
前にも書いたが、RAIIとGCは直接の関係はないよ。
現にC++/CLIでは、ローカルスコープのオブジェクトがスコープを抜けた時点、あるいは
gcnewで作成されたオブジェクトがdeleteされた時点で即座にデストラクタが実行されて
メモリの回収自体はGCで行われる。
0419デフォルトの名無しさん
垢版 |
2016/03/27(日) 01:02:24.98ID:MdJCnp0Y
>>415
そもそも不可視のコードでリソースを解放するのが愚行そのもの
プログラマとしての良識があるならusingを使いなさい
RAIIなどというくだらないバッドノウハウはC#では必要ない
0420デフォルトの名無しさん
垢版 |
2016/03/27(日) 01:31:49.74ID:vj+h39OC
>ローカルスコープのオブジェクトがスコープを抜けた時点、あるいは
>gcnewで作成されたオブジェクトがdeleteされた時点で即座にデストラクタが実行されて
>メモリの回収自体はGCで行われる。

それはGC関係ないRAIIの話だろ
C#でもusing使えばRAII出来るが
usingも、ローカル変数も、deleteも、何れもGCじゃない
手動で寿命管理しているに過ぎない

寿命管理を自動化(GC)しつつ、RAIIを実現する話をしているわけだが
どんな場合でも、GCで有ろうが無かろうが、手動でデストラクタなりファイナライザなり呼び出せば
RAII出来るに決まっているだろ、それに何の意味が有るんだよ
自動化の話だよ
0421デフォルトの名無しさん
垢版 |
2016/03/27(日) 01:33:16.88ID:vj+h39OC
>そもそも不可視のコードでリソースを解放するのが愚行そのもの

その最たるものが、マークスイープ系GCなわけですが
いつ実行されるかすら分からない
まさに不可視
0422デフォルトの名無しさん
垢版 |
2016/03/27(日) 01:51:43.15ID:vj+h39OC
極端な話
mallocして使い終わったらfreeして
はい、手動でRAII出来ました!って主張
それ何の意味が有る話なの?ってね
0423デフォルトの名無しさん
垢版 |
2016/03/27(日) 07:41:27.84ID:kBj57j3O
>>420
>それはGC関係ないRAIIの話だろ

メモリはGCで回収されると書いたが?あと、そもそもRAII自体がGCと直接関係ないとも書いた。

>usingも、ローカル変数も、deleteも、何れもGCじゃない

いずれもメモリ領域はGCで回収される。

>どんな場合でも、GCで有ろうが無かろうが、手動でデストラクタなりファイナライザなり呼び出せば
>RAII出来るに決まっているだろ、それに何の意味が有るんだよ

ローカルスコープに置いたオブジェクトは手動で呼ぶ必要はない。
gcnewで作成したものにはdeleteを使うってのは普通のC++と同じだ。
ローカルスコープの変数を基点に、スコープを抜けたときに連鎖的にデストラクタが呼ばれて
delete等の後始末がされるってのがRAIIだからな。
普通のC++ではそのdeleteのときにoperator deleteでメモリ領域が解放されるが、C++/CLIでは
GCで回収されるというだけ。

「GCで有ろうが無かろうが」「RAII出来るに決まっている」ということを理解したならまぁそれでいい。
できないってのを否定しただけで、別に意味があるかないかを話していたわけじゃないからな。
要は、GCを使う多くの言語でRAIIができないのはデストラクタの仕組みを持っていないからであって、
それがあるC++/CLIならRAIIも可能ということ。逆にGCを使わない言語でも、デストラクタがなければ
RAIIは不可能。
つまり最初の結論、RAIIとGCの有無に直接の関係はない。
0424デフォルトの名無しさん
垢版 |
2016/03/27(日) 10:01:03.80ID:MdJCnp0Y
メモリとその他のリソースを混同して考えるからダメ
まずその他のリソースは不可視のコードで解放しちゃダメ
リソースのスコープは明示的でなければならない
これはデストラクタにもGCにも任せられない
逆にメモリは不可視のコードで解放してもよい
まずこの基本原則から話を進めよう
0425デフォルトの名無しさん
垢版 |
2016/03/27(日) 10:12:42.93ID:Ap0rkncx
schemeにはdynamic-windみたいな他所に継続が飛んでも後処理が保証される仕掛けがあるし
デストラクタがない==RAIIできないにはならないと思うの・・・
0426デフォルトの名無しさん
垢版 |
2016/03/27(日) 11:03:59.82ID:+zMq83Ww
>>424
んな事はない。
あらゆるリソースの寿命はライブラリでデフォルトの管理がされるべきであり、使用者の完全性を前提にすべきではない。
0427デフォルトの名無しさん
垢版 |
2016/03/27(日) 11:16:32.31ID:MdJCnp0Y
>>426
銀の弾丸は無い
あらゆるリソースのあらゆる利用形態に対してデフォルトの動作を定義できるなら話は別だが無理だよね
結局は人が方針を決めて書くしか無い
幸いにしてメインメモリにはRAIIやマークスイープという正解が見つかっているのでそれを使えばいい
だが他のリソースはダメだ
0428デフォルトの名無しさん
垢版 |
2016/03/27(日) 16:21:42.54ID:vj+h39OC
>>423
そんな基本的なことを言って何がしたいの?

RAIIとGCは密接な関係が有るんだよ
君はローカル変数が好きみたいだから、ローカル変数の事例で説明するとする
(嫌ならC#のusingと読み替えてもらっても構わない)
ローカルに確保したオブジェクトが、メンバ変数に他のオブジェクトを持っていたとする
いわゆるコンポジションの状態、よくある話
C++で言えば、class my_class{ object *obj; }; といった感じのクラスになる、分かるよね?
で、ローカル変数はスコープを抜けたら解放される、usingも似たようなもの、これはRAIIの基本、良いね?
このとき、マークスイープ系GCだと、my_classのobjに他からの参照が有るかどうか、即座にわからないので
objを開放してよいのか判断が付かない→my_classは破棄されてもobjはGC発動まで保留される→objは残るのでRAIIの意味がない

もしくは、my_classのobjに他からの参照が全く無いことをプログラマが保証して
my_classの開放部にobjをdeleteなりdisposeなりするコードを記入する
しかしこれは、objの所有権がはっきりしていないことには使えない上に、「手動」である
C++の場合はスマポが有るのでまだましだが、C#のDisposeは完全に手動で呼ばなければならない
自身のメンバにIDisposableなメンバいたら、自身もIDisposableにしなければならず、Disposeメソッドを実装して
自身のメンバのDisposeを芋づる式に呼び出すコードを手動で書かなければならない
mallocしたらfreeしましょうと一緒で、C言語レベルの全くの手動になってしまう

参照カウンタ方式のGCではこれらの問題は発生しない
他からの参照が有るか無いかは即座にわかるし、参照カウンタが0になれば、その場で即座に破棄される
自身のメンバに対して、デストラクタは芋づる式に呼び出されるので、C#のDispose実装のような面倒さは無い

>>424
お前言ってること無茶苦茶すぎるだろ

>リソースのスコープは明示的でなければならない、デストラクタにもGCにも任せられない

GCはともかく、デストラクタでもダメって意味不明すぎるんだが
考えの根本がおかしい
0429デフォルトの名無しさん
垢版 |
2016/03/27(日) 16:43:31.54ID:vj+h39OC
C++で書けば
struct A{ *obj };
void func()
{
  A a;
}
こういったRAIIの場合のobjの開放はどういう扱いにするんだって話

aが完全にobjを所有しているケースなら、Aのデストラクタにdelete obj;とでも書くかscoped_ptrでも使えばよい
しかし、objが彼方此方から参照されている可能性もあるので
そこんとこコンパイラは判断が付かないので、自動化はきない
あくまで、プログラマが保証する形になる
C#のDisposeのような仕組みを言語側で用意したところで、自身のメンバにIDisposableなメンバが有るかどうか
いちいち調べなきゃならなないし、調べ忘れや呼び出し忘れをするという問題が出てくる
しかも、所有権が単一である場合にしか成り立たない

一方でマークスイープ系GCに任せっぱなしにすると、objの開放はGC発動まで遅延してしまうだろう

参照カウンタはこれらの問題をすべて解決する
参照数はどのタイミングでも直ぐに分かるし、0になれば遅延なしで即座に削除される
デストラクタは自身のメンバに対して芋づる式に自動で呼び出されるので
スマポを使っておけば呼び出し忘れるということもないし
Disposeのような冗長なコードを書く必要もない
0430デフォルトの名無しさん
垢版 |
2016/03/27(日) 16:44:43.86ID:vj+h39OC
訂正

struct A{ *obj };
void func()
{
  A a;
}



struct A{ object *obj };
void func()
{
  A a;
}
0431デフォルトの名無しさん
垢版 |
2016/03/27(日) 17:07:08.54ID:vj+h39OC
結局、C#のDisposeはどこまで行ってもどんなに進化しても手動で書かなければならない
自身のDisposeが呼ばれたからと言って、自身のメンバ変数のDisposeを芋づる式に勝手に呼び出して良いかは
コンパイラにはまったく判断が付かない
他からも参照されていて今まさに使われている可能性がある以上
コンパイラが勝手に自動でDisposeを呼び出すコードを生成することはできない
GCを発動してみるまでは、どこからも参照されなくなったことが保証できない
しかし、GCの発動まで開放が遅延しても良いのであれば、そもそもDisposeは要らないわけで
Disposeの実行はGC発動より先行していなければならず、GCに頼れないということになる
なので、自身のDisposeが呼ばれたときに、自身のメンバのDisposeをしてよいかは
プログラマが考え、手動で呼び出す必要が有る
所有権が単一であれば、手動でメンバのDisposeを呼び出せばよい
手動で記述しなければならないので面倒くさいし、ミスの元ではあるが、一応できる
所有権が複数であれば参照カウンタを使うしか現実的な方法は無いだろう
マークスイープ系GCなのに参照カウンタで独自に管理するのは馬鹿げているがな

参照カウンタ方式+デストラクタ
であればこれらの問題は一切発生しない
参照カウンタが0になったことは即座にわかるし、デストラクタはメンバ変数に対して芋づる式に呼び出されるので
開放に関しての特別なコードを手動で書く必要は無い
開放処理も一本化される
0433デフォルトの名無しさん
垢版 |
2016/03/27(日) 17:17:01.33ID:MdJCnp0Y
>>428
バカすぎる
細かい事気にせずデストラクタで解放すりゃそれでおkって感じの適当な現場でしか働いた事無いんだろうな
0435デフォルトの名無しさん
垢版 |
2016/03/27(日) 17:24:21.54ID:MdJCnp0Y
まずDisposeは生成できる
めんどくさいという奴は知識が無いだけ

リソースを共有する事は少ない
というか設計段階で可能な限り少なくする
そして共有するならするでしっかり管理して自動解放などという手抜きはしない
基本中の基本だ
0436デフォルトの名無しさん
垢版 |
2016/03/27(日) 17:32:09.52ID:+zMq83Ww
デストラクタで解放してはいけないリソースをデストラクタで解放しなければいいだけで、デストラクタで解放すればいいリソースはデストラクタで自動的に解放すべき。
0437デフォルトの名無しさん
垢版 |
2016/03/27(日) 20:12:26.78ID:kBj57j3O
>参照カウンタ方式+デストラクタ
>であればこれらの問題は一切発生しない

.NETのマーク&スイープGCの上でRAIIを実現している実例としてC++/CLIを説明したんだが、
「基本的なこと」とか言いながら結局何も理解してないんだな。

そもそもRAIIの話で所有権が共有されたオブジェクトを持ち出すのが意味不明すぎる。

>参照カウンタが0になったことは即座にわかるし、

「いつか」全員が所有権を手放したら「即座に」破棄される
「いつか」全員が所有権を手放したら「いつか」GCで破棄される

どう違うというのか。
0439デフォルトの名無しさん
垢版 |
2016/03/27(日) 21:10:56.38ID:N7IGtcj3
グローバルインスタンスホルダーは明確にインスタンスの状態を把握したいときに積極的に使うべき
0440デフォルトの名無しさん
垢版 |
2016/03/27(日) 22:32:53.86ID:vj+h39OC
>「いつか」全員が所有権を手放したら「即座に」破棄される
>「いつか」全員が所有権を手放したら「いつか」GCで破棄される
>どう違うというのか。

少なくとも最善が尽くされるという意味で違うし
同じデータと同じプログラムで有れば、常に同じタイミングで開放処理が走るという再現性が有る

それから、自分しか所有権を持っていない場合、つまり参照数が常に1というシンプルな状況ですら
参照カウンタ方式の方が開放処理が自動化されて楽

参照カウンタ方式で有れば、スマポを使っておけば済む
scoped_ptrでも良い

マークスイープ系GCであれば、自身しか所有権を持たない単純な場合でも
非常に面倒なことになる
自身にDisposeを実装して自身のメンバのDisposeを呼び出すコードを手動で書かなければならない
何故こういったコードをコンパイラが自動生成できず、手動で書かなければならないのかの根底に
まさにマークスイープGCの存在が有る
マークスイープ系GCは何処からも参照されなくなったことがその場ですぐに分からない
GCを発動してみるまで保証することが出来ない

自分のDisposeが呼び出された、まさにその瞬間に、自分のメンバに対してもDisposeしてよいのかどうなのか
参照数がリアルタイムで即座に分からないので判断する材料が何も無く
コンパイラはC++のデストラクタのように自動で芋づる式に開放処理を呼び出すコードを生成することが出来ない

要するにマークスイープ系GCではDisposeのコンパイラによる自動生成が出来ないという大きなマイナスが有る
0442デフォルトの名無しさん
垢版 |
2016/03/27(日) 22:41:25.16ID:VNvh7E4d
>>440
子要素をDisposeしていいかどうかもわからないってそりゃ設計サボってる以外のなんでもないだろう
ちゃんと設計してればいつ削除してよいかなんてわかるはずだろ
まともに設計もできないレガシーエンジニアは黙っててよ
設計に時間使わないとリソース云々以前に別のバグだらけになるぞ
0446デフォルトの名無しさん
垢版 |
2016/03/28(月) 00:20:40.85ID:j/beyn8U
>>440
前者(参照カウントGC)はRAIIができるが後者(マーク&スイープGC)ではできないというお前の
主張について言っているんだが?
「最善が尽くされる」からRAIIができて、尽くされないからRAIIができないとでも言うのだろうかw

>要するにマークスイープ系GCではDisposeのコンパイラによる自動生成が出来ないという大きなマイナスが有る

何度も例に挙げているC++/CLIでは、デストラクタを記述するとコンパイラによってDisposeが追加される。
そして、ローカルスコープに置いたオブジェクトに対してはスコープを抜ける際に自動的にdeleteが呼ばれる。
そこからdelete→Dispose→デストラクタと呼び出される。RAIIに必要なものは揃っているし、事実、可能だ。
もちろん、そのメモリ領域は別のタイミングでGCによって回収される。

ここまで説明しても理解できない低脳ならしょうがない。
やはりデストラクタとファイナライザの違いが理解できてないようだからそこから勉強しなおせ。
0447デフォルトの名無しさん
垢版 |
2016/03/28(月) 00:39:52.48ID:2h3yopdG
{
std::shared_ptr<my_namespace::my_class> p(new my_namespace::my_class(...));
/* unko_code */
}

using(var obj = new MyClass(...)) {
/* GoodCode */
}

美しいという事はいい事だね
C#は書いてある事がシンタックス的にもセマンティック的にも明確だ
リソース管理はこうでなければならない
0452デフォルトの名無しさん
垢版 |
2016/03/29(火) 01:50:13.51ID:40IzaG0J
c++なら普通こうだな
{
my_class obj(...);
...
}
そういやc#でp.release()相当の事って簡単にできるの?
{
auto p(make_unique<my_class>(...));
...
}
nullって代入可能?
0457デフォルトの名無しさん
垢版 |
2016/04/13(水) 15:29:31.16ID:oOcEPJTu
GC大好きっ子に聞きたいんだが
完璧な(理想的な)GCを搭載したメジャーな言語処理系って何があるの?
これで開発すればリークも管理も気にしないでOKってやつ
0458デフォルトの名無しさん
垢版 |
2016/04/13(水) 16:22:35.14ID:s5MRiDQ8
無い

マークスイープ系GC → 循環参照OK、しかし即座に開放されない
参照カウンタGC → 即座に開放される、しかし循環参照NG

ということで、理想のGCは無い
全てのGCは何かを妥協している

それから、たとえGCを使ったとしても
要らなくなったオブジェクトの参照をいつまでも握っている奴が居たら解放されないから
リソースの管理をしなくてよいということは無い

あと、GCは基本的にメインメモリに対してしか有効に機能しないから
例えばファイルオブジェクトなんかは要らなくなったら即座にcloseするなりすべきで
リソース管理フリーというわけにはいかない
0459デフォルトの名無しさん
垢版 |
2016/04/13(水) 16:54:16.68ID:s5MRiDQ8
つまりは、GCを使っていたとしても
君がオブジェクトを何処かに登録したなら
オブジェクトが要らなくなったら登録解除してあげないと
そのオブジェクトは解放されないのだ
これはちょうどmallocしたらfreeしましょうに似ていて
GCを使ったとしても全てのリソースの管理が自動になるわけではないということだね

究極的にはGCの利点は自分でfree/deleteをしなくても良いところにある
これはつまり、ダングリングポインタが発生しないということだ
0461デフォルトの名無しさん
垢版 |
2016/04/17(日) 16:17:55.58ID:j/f/oFPY
そして無視されてしまうコピーGC君
GCの利点は自分で大量にメモリの確保&解放するプログラムにおいてバグが出にくくスループットも出るってところだと思う
もしheapをそんなに頻繁に確保&解放しないんだったらGCない言語の方がいい
ただ近代的な言語は少数の例外を除いて大抵GC積んでるけど
0462デフォルトの名無しさん
垢版 |
2016/04/17(日) 16:21:44.96ID:j/f/oFPY
>リソース管理フリーというわけにはいかない
リソース管理フリーについてはrustみたいなGCない言語のほうが達成できてるよね(あとは関数型言語か)
でもrustでもリソースの解放時にエラーを吐く可能性がある処理なら自分で解放する処理書かなきゃいけないっぽいけど
0463デフォルトの名無しさん
垢版 |
2016/04/17(日) 18:35:17.89ID:SAR9JCaP
RAIIでも結局どのタイミングで解放されるか意識しなくてもいいってわけじゃないし
リソース解放処理を書かなくていいだけで
0464デフォルトの名無しさん
垢版 |
2016/04/17(日) 18:43:59.82ID:cFoKw8Zx
メモリ管理系のバグが顕在化しにくいだけで、そこら辺適当なまま中途半端にキャリアを積む開発者を量産するという害悪が大きい。
JNIやらで他のAPI使う必要が出てくると結局いろいろ配慮しなきゃいけなくなるし。
0466デフォルトの名無しさん
垢版 |
2016/04/17(日) 19:50:47.36ID:1R/4ebGS
>メモリ管理系のバグが顕在化しにくいだけ
結局これだよね
本当に丸投げできるなら乗っかるのもいいと思う
性能問題はハードの進化で一部の用途を除けば問題無くなると思うし
でも現実は中途半端だから意識して書いたほうがマシだと
0467デフォルトの名無しさん
垢版 |
2016/04/17(日) 21:19:09.59ID:IB74e9ph
ムーブセマンティクスのおかげでずいぶん便利に。
■ このスレッドは過去ログ倉庫に格納されています

ニューススポーツなんでも実況