GC、ガベージコレクション、ガベージコレクタ、ガーベジコレクション、ガーベジコレクタは使えない。 以下GCと記す プログラマをメモリ管理から開放する! といいつつ、メモリリーク問題の文献が大量にある。 これすなわち、メモリリーク問題が全然解決していないということ。 さらに、メモリ解放のタイミングの文献まで大量に生み出した。 これすなわち、新たなるメモリ管理に関する問題を生み出したということ。 malloc、freeじゃないが 結局のところ、メモリを管理するという技術は、今しばらくは、身につける・教える・学ぶべきではないだろうか? 使って、そのまま放置しても、基本的にはGCがなんとかしてくれている。 ランジョブからジョブ終了までさほどの時間を要さない。メモリも大して使わないならいいだろう。 しかし、規模が大きくなり常駐ジョブやメモリ大量使用のジョブになってくると、そんなメモリ管理の方法でやっていると、 上記「文献」を生み出されてしまう。 入門時は、メモリに無頓着でもいいだろう。それよりも、目的を達成することが先決だ。 しかし、慣れてきたら、やはりメモリの管理まで余裕を持って自分で行うべきだろう。 前スレ GCは失敗。メモリは自分で管理せよ! http://peace.2ch.net/test/read.cgi/tech/1412986420/ なるべくスコープを狭くして長時間存在するオブジェクトを無くす 以上
仮にmalloc/free型を長時間動かしてたらフラグメントが酷いことになるぞ そういう問題もコピーGCなら一気に解消できるしGCの方が耐久力があるよね
GCの無い時代のプログラムでフラグメントが問題になった例をあげてみろよゴミッカスw
>>3 それGCのない言語の問題じゃなくてC/C++の問題だろ コンパクションとGCはあくまで別だし 519 :名無し~3.EXE:2015/11/19(木) 21:49:08.84 ID:CEKgHuEl 他のアプリを使用しながらSleipnirを使う メモリー不足でのメッセージは良心的 問題点として、場合によってはメモリー不足で メッセージされずに展開されなくなる Sleipnirが不安定で信頼感を得られない要因 520 :名無し~3.EXE:2015/11/19(木) 21:51:47.06 ID:CEKgHuEl 6で書き込み欄が展開されなくなった・・・再起動してカキコした 521 :名無し~3.EXE:2015/11/19(木) 21:52:39.96 ID:CEKgHuEl ◆重要◆Sleipnirが不安定で信頼感を得られない要因 525 :名無し~3.EXE:2015/11/19(木) 22:13:05.49 ID:CEKgHuEl 展開されない時 リロードで展開される場合もあるが リロードで展開ない場合もある
メモリ管理は自分でやった方が漏れが出るでしょ 規模がでかくなればなるほどリスクが大きくなる
C#の基本は自動だけど部分的に手動にできるハイブリッドがいいと思うよ 確保量の大きい画像なんかを扱っているとどうしても手動で解放したいタイミングもあるし
>>10 それが理想的だけど、C#ってそんなことできたっけ? 調べてみたけどよくわからんな。 もしかしてアンマネージなメモリを確保してデータ領域に使う話?
アンwwwwマネージwwww 無理に横文字使わなくていいですよwww
c#が残念なんのはC++とデストラクタの呼ぶれるタイミングが違いすぎて移行が大変すぎることだ。 結局、手動でデストラクタを呼ばなきゃならない。GCの利便性がほとんどなし。
>>9 自動ならメモリリーク等々発生するわけがないのに発生している この原因はプログラマなんだけど、結局メモリ管理から解放されてないなら最初から管理する方針でいいじゃん メモリ管理を楽にするためにあるわけで人間が全部面倒みんのとは違うだろ
やっぱりGCのほうがいいかな大規模になってくると Cでリークはしてないけど本来開放すべきタイミングで開放してないでメモリいっぱいになるのは防ぎやすいと思うし
>>20 楽になってメモリリークがなくなるならいいけど、メモリリーク発生するわ プログラマがメモリ管理なんてしなくて大丈夫、とメモリの扱いが雑になって意図しないタイミングで解放されたりされなかったり 最初から管理するという方針で教えないから、こんなことになる 管理漏れをGCがうまいことやってくれる。でもGCにやらせるようだと恥。 というくらいで教育すべき メモリ管理すらまともにできないやつが寿命や世代やら管理できるわけがない。
GCそのものではなく新人教育や解説書が最初のスタンス間違えたんだよ。 GC=メモリ管理適当 という認識作ったから、GCに新しい名称つけて 教育や解説書では、メモリーの確保から解放まできちっと説明し直したほうがいい
GCって完全なものだと思ってたから、C#案件でメモリリークの調査にえらく手間がかかった GCはダメな子って認識は必要だな
C/C++はライブラリレベルでメモリリリークの検査もテストも書けるけど GC前提言語だとその辺がごっそり抜け落ちて後で問題になる
メモリ管理できない人がお気楽で作れば、GCあっても・・・・
前スレでも書いたけど、C#のDisposeの問題を紹介しよう IDisposableなオブジェクトをコンポジションしてメンバに持つと自身もIDisposableにしなければならない だから自分がコンポジションしているオブジェクトがIDisposableかどうか一々調べなければならないし IDisposableなオブジェクトがメンバにあれば、自身もIDisposableにしなければならない さらに、その作ったクラスをコンポジションして使うクラスもIDisposableにする必要があり・・・ という風にIDisposableはクラスで閉じずコンポジションで伝染する というか、むしろ手動で伝染させなければならないという しかもIDisposableの一連のイディオムはとても長くて煩雑 http://ufcpp.net/study/csharp/rm_disposable.html こういうものを書いて、マネッジドリソースとアンマネッジドリソースで場合わけをしつつ IDisposableなオブジェクトに関しては 手動で自分のメンバのDisposeを漏れなく呼び出すコードを書かなければならない 当たり前だが、どのメンバがIDisposableか完全に把握しておく必要が有る 手動で自分のメンバのDisposeを呼び出す作業は、まるでCのmallocを思い起こさせる 問題点は明確で、DisposeがC++のデストラクタのように芋づる式に勝手に呼ばれない事に有る だから手動で芋づる式に呼び出すコードを書かなくてはならない Formなんかも参照が亡くなったら強制的に殺すべきだったと思うわ ファイナライザーの処理がひどいことになると思うけど
解放処理をしなくてもGCがやってくれる。 でも、ソースに解放処理が書いてあれば、後から見たらあぁここで用済みになったのかとわかる。 可読性は非常に重要よ。
解放処理のタイミングが制御できないと、解放して欲しくないタイミングで解放されて 挙動が変わることがある リアルタイム性が要求されるシステムでこれで困ったことがある(そもそもそんな言語使うなって話だが)
>>35 それはあまりない 挙動が変わるというか停止するというのならあるのかもしれないが >解放して欲しくないタイミングで解放 なんでそんなことになったの? 参照切ってなきゃGCの対象にならないはず
空きメモリによって使用するアルゴリズム変えたりする。 だから実行前にGC手動で走らせて、できるだけ空きメモリ増やしたりとかする。 できるだけ開放したいのに過負荷でまだメモリに余裕あるからGC走らないってのが困る。
メモリの解放漏れってさ、とどのつまり下手だからするんだよね 下手なやつにはプログラムを組ませないってのが鉄則だと思うの
c++11のshared_ptrの参照カウンタってそもそも要るんだろうか? 複数のオブジェクトが所有権を持ちあう必要性に迫られる事がないんだけど weak_ptrの対応だけあれば良くない?
リソースを共有する場合なんかは使うと楽だよ まーshared_ptrが有れば、いつ実行されるか分からないような、手の込んだGCは要らないよな 巡回参照が有る場合はどちらかをweak_ptrにする、これだけを守ってれば問題は起きない 大体の場合は所有権というか上下関係がはっきりしているからな 巡回参照のある場合も自動で開放したいという、たったこれだけのために いつ実行されるか分からない上に重いマークスイープ式GCを導入するのは 業界全体の早とちりだったようだね
最近のC++はdeleteを直接書かないだけでなく、最早newも直接書かない方向 std::make_shared<int>() って書くよね 始めからshread_ptrで受け取るから、循環参照だけ気をつければ リークする余地がないよね RAIIも健在で、C#みたいにIDisposableとか要らない デストラクタも芋づる式に呼び出されるから >>30 で書いたような問題も起きないよ >>41 糞便利な参照カウンタを使わないなんてC++使う意味なし >>42 それはManagerやHolder的なものを書かなくて良いってことを言ってるの? それって大体一時しのぎで大抵後々リソース管理以外にもそういった管理クラスが必要になるケースがほとんどじゃない? >>45 ねーよ うーん質問がアバウトすぎたな。もう少し具体的に書くわ 例えば2chのある板を管理するプログラムを書くとして BoardクラスとThreadクラスを想像してみてくれ BoardはThreadオブジェクトを管理するが、Threadは 産まれたり死んだりと揮発的で寿命が定まらないと。 で各Threadは何らかの共有リソースを持つと。 例えば一度読み込んだ画像を各スレッドで共有したいとかが 考えられるけど、画像オブジェクトをshared_ptrで共有するのは 適切ではない なぜならある瞬間に産まれたThread群がひとつの画像を共有する からといってshared_ptrで持たせたとしても、後の更新時に 更にその画像を共有したいThreadが現れたときに、画像が すでにあることを何らかの形で知れないといけないから。 結局Boardなんかが画像オブジェクトのコンテナを持つ必要が あってそのコンテナへの追加と削除のために別の共有の 仕組みが必要になるんだよ。例えばThreadがBoardに画像を リクエストして参照カウンタを持ったアクセサを返すようなもの だから所有権はBoardひとりが持てばよくてshared_ptrを 使う必要がなくなるという理屈 こういったケースを踏まえてもshared_ptr使うケースって ほとんどなくね
IDisposableの問題はDisposeを呼ばなければリークするものとそうでないものの混在だろ
>>47 マルチスレッドプログラム書いてみろよ shared_ptrがないと泣くぞ >>49 いやいくらでも書いてるけど基本一緒 というか上の例もそのままマルチスレッドに適用できる話でしょ 例えばproducer consumerならproducerが所有権を持つし thread per messageなら共有データはホストが持って固有データは 個別スレッドで持つだけ むしろマルチスレッドの場合、所有者をより厳格に決めとかないと 泣く事になるぞ 所有権って・・・・ unique_ptrを使うと勝手に所有権が移動してしまうし 生のポインタを使うんならわかるけど
shared_ptrで複数人が所有権を持っても良いんだぞ 上下関係さえしっかりしていれば良い
そんなの分かってるんだが >>50 の人はどう考えてるのか >>51 今のC++からshared_ptrをそのまま無くせって言ってるんじゃないぞ shared_ptrのコピーを禁止にしてweak_ptrの対応だけあれば良くないかって事 そもそも何でそんなこと言うかっていうと、 GCない言語→循環参照ガー。みたいによく言われるけど使わないで 済むなら静的解析で循環参照の起こり得るケースをエラーにしてしまう って解決方法もあるかなと思っただけ あとshared_ptrとweak_ptrはアトミック操作とメモリバリアを必要としうるから それに頼った設計は疑問を感じる 一応言っとくと静的解析のくだりは新しい言語を 設計するとした場合の話ね C++だとほぼ不可能だろうから
せっかくC#は新設計なのにいろいろ失敗が含まれてるよな。 ヘジはなにやってんだか。
大企業は、 中小企業を奴隷にさせる事を第一に考えたツールしかリリースしてないよ 失敗ではなく全部わざと。
メモリ管理テケトーなやつはその他のリソース管理もテケトー
そもそも自分のリソース管理がしっかり出来てる人は・・・
>>31 Formはnull入れてあげないといけないんだっけ? なんか、場合場合によってnull入れてあげないといけなかったり入れなくてもよかったり。 ならnull入れるで統一でいいじゃんと思った 中の細かい実装まで知らないんだけど、 A = new A() Loop Begin 処理 A = null A = new A() Loop End とか、nullをセットをGCって見張ってるの?又はGCに伝えているとかあるの?
違うよ newが動いた時点で中の人がメモリが足りない!って騒いで初めてGCさんお願いします!GC「やれやれ・・・ っていう仕組みなんで >>62 の例のnullの代入は無駄 いや無駄じゃないか 代入演算子の順序の関係でnewの後に代入が起こるから Aを事前にnullすることでGCさんが回収できるオブジェクトが1個増える
>>64 つまり、使い終わったら、スグにnullっておいたほうがいいってことか。 ・・・とも言い切れないな。 でも、ここで使い終わったってわかるから、書いたほうがいいか。 よし。決めた。全部書こう。 null代入なんていちいち書いていたら コードが冗長になって保守性が落ちる。 メモリ食いのオブジェクトなど、クリティカルな部分でのみ使うべき
null代入とか結局やってることc++以下なんだよなぁ
ダングリングポインタが出ないって利点は有るにはあるが スマートポインタ使えば済む話だしなぁ weak_ptrもあるし
>>68 ここでおしまい!って書いてあるだけ。 こんなんで冗長とは評価されない。むしろ読みやすい。と判断した。 変数がどこで不要になるか明示しなきゃならんほど長い関数ばっかり書いてるのか それともローカル変数とか無い言語を想定してるのか
保守性より効率重視なんかでコード書くからメモリリークするんだよ。
どんな意味でnull代入をしてるのか他人に伝わらなきゃ保守性もクソも無いよね
a = null; で伝わらない人にはどんなコメント書いても伝わらないと思うんだ。
関数内ローカルな変数は いくら大きくても大概スコープだけで どうにでもなる。 javascriptみたいなのはlambdaでスコープ切ればいい。
>>75 ,>>77 同じ結論ですわ。 null代入ってやっぱり特殊だから、コメントよりはるかに目が行く。 ここで使い終わったYO!!(逆に言えば、ここまでは意識してね。使ってるから。)ってわかってもらえれば良い。 >>77 長い関数中にそれ出てきたら変数を使い回す前に初期化したいのかな?とかも考えるな 短い関数なら変数を使い終わったとか重要な情報じゃないから無駄な行入れて可読性下げてるだけ 永続的な変数でもなきゃ、変数の寿命はコンパイラが把握しているから、null代入がどんな変数にも必要なら勝手に挿入するんじゃね。 そうじゃないとしたら、なんでもかんでもnull代入が必要なんてのは幻想だよ。
勝手にnullを代入するとか、そんな変なコンパイラは困る
話は変わるんだがスマートポインタのメリットって何? コンストラクタで例外投げたとき そこまでに初期化したメンバ変数のデストラクタを呼ぶため みたいなのは聞いたことあるけどそれくらいのもん?
>>83 別にコンストラクタじゃなくて関数内で確保した場合でも、 例外じゃなくreturnで戻った時も勝手に解放してくれたほうが 有り難いし、そもそも解放処理って忘れやすいものだろ 傘を置き忘れたり洗濯物を洗濯機に入れっぱなしにしたことの ないものだけスマートポインタに石を投げなさい null 代入したら行数増えるじゃん…全部のローカル変数にやってんの? どうしても明示したければスコープで区切った方がまし それでもインデントが深くなるのであれだけど
>>82 勝手にnull代入すると表現するから気持ち悪く感じるだけで、コンパイラが各変数についてもうアクセスされる可能性の無い基本ブロックに到達したら、その変数をGCのマークの起点として使用しないようにフラグを管理すると言えば当たり前の話じゃね。 フラグの持ち方として変数にnullを代入しているだけで。 >>84 > そもそも解放処理って忘れやすいものだろ それを忘れるなどとんでもない 確保&開放なんてプログラミングの花じゃん キモじゃん そこを工夫するのが楽しいんじゃん 設計も楽しいし チマチマテストすんのも楽しい 温泉行って湯につかり忘れる心配はない >>87 まあ勉強目的でやるならいいんじゃね 俺は元々ゲームプログラマだったからもう嫌になるほどやったし メモリ周り工夫するなら言語設計からしたいわ 信じて送り出した >>87 がわがままな顧客を✕✕して三面記事に載るなんて… マークスイープ型のGCが必要かどうかについて、もう少し建設的な会話をしようよ リソースを自動で開放してくれる機能は、無いよりは有った方が絶対に良い、と言い切ってよいよね ただ、その方式が話の焦点だと思う C++のスマポの参照カウンタ方式はデストラクタとの相性が良いし、RAIIもよく機能するし 開放されるタイミングもはっきりしているのて、手続き型言語と相性が良いし、軽い ただし、循環参照があるとリークする 解決策として、片方をweak_ptrにするという方法が用意されている weak_ptrは対象オブジェクトが開放されると勝手にヌルポみたいになるのでいろいろと悪用ができる 一方でマークスイープ系のGCは、循環参照があってもリークしない しかし参照カウンタ方式に比べてマークスイープ系のGCが優れている点は、それだけ 重いし、いつ開放処理が実行されるか分からないので リソース開放のタイミングを明確に行いたい場合のための別の仕組みが必要になった どちらを選ぶ?
そもそもc++においてメモリリークって対策も発見も 大して難しい部類のバグではないんだよなぁ GCの優位性をアピールするために過剰に恐怖心を煽ってる気がする
>>92 その程度の案件しか受けてないからだろう。 >>90 つ世代別GC immutableオブジェクトをバンバンnewしまくる関数型プログラミングに慣れてると やっぱGCないとキツイわ >>93 いやいや普通難しいとされるバグってメモリ破壊とか同期周りだから メモリリークなんてデバッガがチェックして丁寧なダンプ出してくれるし 組み込みとかの貧弱な環境なら専用のメモリ管理を用意して いくらでも好きなチェックや情報出せるから >>92 それな メモリの確保と開放の対応すら管理できない奴は なんかもう何をどうしたってダメな気がする 初歩の初歩の初歩の話題を何度も何度も何度も繰り返しすぎ 忘れるとか忘れないとか池沼レベルの話じゃん。 ゴミクズ。 メモリの解放が必要ならそれは必要な機能の実装ってことになる。 それを忘れるってことはプログラムを組んでいて必要な機能の実装を忘れるってことだ。 必要な機能の実装を忘れるということは、例えば通販サイトのシステム開発請け負っておきながら、決済システムを実装し忘れるのと同等。 ありえない。 プログラム云々以前に頭の問題だろう。 必要な機能の実装を忘れる可能性におびえる池沼プログラマ。 最近流行りのADHD?なんじゃねえの。
>>95 なるほど。経験の少なさがすぐ分るな。ログ出したらで数十ギガなんてよくあるよ。 ログから問題点をスクリプトで抽出するにも何時間とかかるとかいろいろ。 マルチスレッド絡んで特定のパターンだけだったりして再現性がなかったりする。 他システムの連携だと手が出せない部分の挙動がおかしい可能性もある。結局、oracleのバグだったとかね。 >>97 決済システムとメモリ解放は違うよ。 通販サイトのシステムをC言語で実装してみればわかるかと。 >>98 はあ?なんでリーク箇所ダンプするだけの話でログ全部吐き出すことになってんの 普通確保する際にヘッダにそのブロックの確保場所埋め込んでるし アロケータで生存期間のスコープを切り分けといてすぐ分かるようにするけど? お前の関わったプロジェクトが糞なだけじゃね? そもそも今時c++でgcならなんとかなる類いのメモリリーク起こすなんて、プログラマが屑なだけ。 リソースリークやその他の問題も確実に起こすこと請け合い。 GC言語でそのレベルのプログラマを使うような案件はGCによるメモリオーバーヘッドが気にならず、リソースリークも問題にならないような非常に緩い案件でしかない。
>>100 はぁ。話にならんな。扱ってる規模が違いすぎる。 >>102 おいおい反論できずに捨て台詞かよ 上でも書いたがコンシューマで開発してたから 100人*数年の規模でやってたんだけど もしかしてC++みたいな危険な言語使ってて 今の今まで解析ツールなり自前のメモリ管理なり知らなかったの? お前ら派遣だろw 全体規模とお前らが任されてる範囲を都合よく混ぜるな。
ほーら、自分の知能が一般人より低いと認めたくないがゆえにレッテル貼りが始まった。 普通の人が当たり前にできることができないってかわいそうだな。 もしADHD?だったら治療法あるらしいから病院行ってみたら? ここでレッテル貼りやってるよりよっぽど解決する可能性が高いぞ。
>>100 リーク箇所がわかってればログ出力の必要なくね? ホントに開発したことあるのかな? >>107 普通C++のプロジェクトは専用のメモリ管理を用意するから リークしたメモリはそれを確保したクラスとその行数まで特定できるようにしてるよ アロケーターも分離しとけばアプリケーション終了させなくても 管理オブジェクトを破棄した時点でリークの判定できるし リーク箇所特定するのに全ログから解析とか複合的なバグでもない限りしない そんな状況許してる時点で負け 100人で数年のシステムなら 10人で一年でやるべきだな。 人を無駄に増やせば、意思疎通や連携に無駄に労力を割く。 開放云々より仕様レベルで齟齬が出やすくなるわ。
>>108 リークしたクラスが分ればリーク原因が分るとかお花畑杉w >>110 誰もリークしたクラスの事なんて言ってないんだが…理解できてる?(笑) 解らないなら解るだけの情報埋めたら? >>112 そもそもGCがあろうとコンテナに突っ込んで消し忘れれば オブジェクト破棄するまでメモリ圧迫し続けるって理解できてる? リーク単体ならC++はそれと同等のレベルまで分かりやすく出来るんだよ C++が困難なのはそういった管理情報も簡単に破壊出来てしまう点 リーク単体なら怖くはない なんかだんだん笑えて来たんだけど、ろくに理由も言わずに 「わかんないんですけど!?わかる奴はお花畑(怒)!!」って なかなか面白い奴だな
メモリの解放すら管理できない奴が、複雑な仕様を管理できるとは到底思えない・・・。 メモリの解放なんてなんの苦にもならんが・・・。
やれやれw MSやLinuxやFreeBSDまでメモリリークやらかす理由が分らないのか。
>>116 また反論できずに逃走かよw そもそも欧米は原因分かっててもバグ無視する連中だろうがw ライセンスで守られてりゃ平気で放置するぞ 人生の管理ができない奴が、メモリを管理できるとは到底思えない
そもそもLinuxカーネルもFreeBSDカーネルもC言語だろ 馬鹿丸出しだなw
>>115 それな プログラミングにおいてメモリ周囲はまだ初歩だよな そしてマルチスレッドはそれよりは大変だがこれも慣れると 結局大事なところをガッチリ排他処理するだけのことだしな プログラミングって最後はインタフェース設計だけだから 使いやすくてコンパクトなインタフェースを求めていくだけ これがプログラミング道の後半の道のり >>120 で例外系の実装がないから破綻するんだよ。実務経験ないとすぐ短絡的になるのが分る。 >>122 馬鹿相手にしても時間の無駄だぞ こいつ具体的なこと何も言わんし >>124 そやね 一連のレスの意図すらよーわからんわ Guilty Crown? たしかに失敗作だったなあ…
GCが云々というより抽象的なプログラミングしたい時は基本的なメモリ管理を言語に任せたいという欲求
>>113 c++素人なんだけどリーク単体はともかくそれにメモリ破壊が合わさると頭がおかしくなって死ぬ みたいな感じ? GCは関数型プログラミングでのみ正当化される 命令型プログラミングでは全く正当化されない 命令型プログラミング(=チューリングマシンに基づく計算モデル)は読み書きの「順序」こそがネ申なので 命令コードの「順序」を横断して存続するブツは善と悪の最終戦争で滅ぼされるであろう つまり確保し、使ったら後開放する、これを明示的に書き下す姿勢こそが正しい
>GCは関数型プログラミングでのみ正当化される ちな、これは処理系の裏方としての存在が許される、の意味
関数型プログラミング好きだけど 代数型データ型と型クラスでモナドとかアプリカティブとかtraverse、free monadとかやってる時に メモリ管理だの言われたら余裕で死ねるな 本物のhaskellプログラマはhaskellで低レイヤを書くらしいけど
>>128 > メモリ破壊が合わさると これが合わさるとなんでもありありなので何が起きても不思議はない なので、ダングリングポインタの管理と配列のレンジチェックはちゃんとやるべし ここでメモリ確保 ここでメモリ解放 たったこれだけが書けない管理できないとかw
メモリリークは開放忘れでなると思ってる低レベルがいるのか。
>>134 mallocでOSから確保したメモリはfreeで解放されないんだが、 「ここで解放」はどうやって書くんでしょう? >>137 や>>139 みたいのが知識や技術に溺れて本質を見失い、 人と会話ができなくなった人の見本なんだろうか >>140 今まで正しいと信じきってた鰯の頭が迷信だと指摘され発狂中 想像を絶するアホは居るもんだよ if (cond) exp; の場合も中カッコを必ず付ける流派ってのがあって 理由を聞くと if (cond) {exp1; exp2;}とするはずが if (cond) exp1; exp2;としてしまうのを防ぐための常に中カッコらしい 中カッコを書き忘れるくらいの意識レベルで書かれたコードって 他のとこももう全部ダメだろそれは
カッコ先につけといたほうが 後々、都合がいいことも
アホな書き方といえば if ( 1 == a ) { って比較元と先を逆にしてる奴
別におかしくない 基準値が先にあって、それと比べてaがどうなのか、と考えるか aが先にあって、基準値と比べてどうなのか、と考えるかの違いでしか無いから どっちでも良い
>>147 知ってて言ってると思うが、定数を==の左辺にするのは if (a=1) { ... と書き間違うのを恐れているらしい >>139 free()から設計し直す、 まあfree()の度OSにメモリを律儀に返していたらパフォーマンスが多少落ちるがGCに精神を汚染されるよりはマシ >>135 スレッド安全に書かない奴が悪いていうかそれは別の話 シングルスレッド状況(またはそれと等価な状況)では>>134 の言っていることは全く正しい ここ数日一気にレベルが下がったなw GCの話しろよw
つーか前スレと同じこと書いてる人多数 頼むから前スレ読んできて
【 オンラインTCGエディター 】 >>1 デュエル・マスターズ的な非電源TCGの 《 オンライン化ツクール系ソフト 》 制作の企画。 例えば、ガチンコ・ジャッジを直ぐにでも導入できる機能を持っておりながら、 当面それを扱わず単純化させておいて、事後的に導入拡張する際に当該システムを ブロック構造の組み合わせで後付け挿入できるように予めシステム化してあるソフト(エディター)。 既存の非電源TCGを劣らずに再現できるならば大概のニーズに応えられる筈。 バトスピ、ヴァンガ、ウィクロス、ポケカ、デジモン、ゼクス、モンコレ、ガンダム・ウォー、ライブオン、ディメンション・ゼロ、カードヒーロー、シャーマン・キングなど のシステムを完全再現できるように設計するけど、他に此のTCGの此のシステムは再現希望とか有ったら書いて。 マジック:ザ・ギャザリングの全システムを完全に再現するのは無理だから、此れだけは必用だ!って部分のみリクエストして。 WEB通信での対戦は、個vs個、多数乱戦、チームvsチーム、個vsチームを可能な仕様とする方針。 設計思想は 《 RPGツクール 》 が良いかな? 他に、優れたエディター有ったら挙げてみて。 個人や企業などのベンダーが提示する開発費(見積もり)で折り合えば、発注する。 ↓ エディター群から基本コンセプトを絞り込む(もちろんオリジナルで優れた新ネタが有れば導入する)。 ↓ 遊戯王OCGに関しては、タッグフォース、ADS、デュエルオンラインを発注先ベンダーに研究させる。 なるべく前述3つで可能な再現は全て実装させる方向を目指す。 まぁ努力する・・・ バトスピ、ヴァンガ、バディ、デュエマなど発売済みゲームソフトが存在してるケースはベンダーに研究させる。 ↓ 各社TCGを再現するテストプレイ ⇒ 更に改良や修正。 ↓ 機能制限した下位版を5万円以上で発売 + デュエリ−グ用に改造した上位版でサーバー稼動=営業開始。 ↑ 下位版の改造および商用利用には、別途で当社との契約が必要。 さ〜て、製作ベンダー見つけよっと!ww(クス http://wc2014.2ch.net/test/read.cgi/entrance2/1449039272/-18 >>149 >free()から設計し直す、 >まあfree()の度OSにメモリを律儀に返していたらパフォーマンスが多少落ちるがGCに精神を汚染されるよりはマシ じゃ>>134 は設計し直してから言うんだな。坊や。 って、事でオッケーね。 >>137 これって何が言いたいの?OSやライブラリ自体にミスがあるって言いたいの? wikiより >メモリリーク (Memory leak) とは、プログラミングにおけるバグの一種。 >プログラムが確保したメモリの一部、または全部を解放するのを忘れ、確保したままになってしまうことを言う。 >プログラマによる単純なミスやプログラムの論理的欠陥によって発生することが多い。 >>137 みたいなこと言う奴って、電磁波からデータが盗まれる!対応しないと!とか言い出すタイプ? >>151 そもそも15年ぐらい前から延々繰り返されてるんだが… >>154 開放コードを忘れずに書いたのに開放されないという怪奇現象がマルチスレッド状況ではしばしばあるんじゃー! マルチコア時代になってこれはますます危険になった 見ただけで正しさがわかる系のスレッド安全策はクロックサイクルを糞のごとく消費するし… こういうのは専門家が徹底的にデバッグしたGCで面倒を見て欲しいと思う反面、 やっぱプロセス全体のごみ処理を選任モジュールにやらせるのはクロックサイクルをドブに捨てるがごとき センス無い設計なキモス、、 >>154 入門書に書いてるコードしか見たことないんだね。 スレッドプールみたいなテクニックは高速化のためにみな普通に使うんだよ。 OSやライブラリにもメモリリークなんてよくあることだし、それらのバグも開放忘れて起きてるイージーなバグじゃないよ。 他のバグやトラブルがメモリリークという形で表面化してるにすぎない。 >>158 具体的にいつのどのバージョンのライブラリで起きてるの? 使い終わったらメモリを開放しろ。使い終わってないなら開放する必要はない。これとスレッドプールとどこに関連性があるの? >>159 詰めても無意味。 こういう連中は、まず自分の考えややり方が絶対正しく絶対に曲げない。曲げないために無理やり理由を当てはめようとしている。 で、さもそれを自分はやってるように言っているが、実際は単に本に載ってることを言ってるだけ。 実装もできない。面前で詰めてやれば発狂して勝敗がハッキリつくけどネット上では無理だね。 メモリの話とスレッドの話を混ぜ込んでしまうタイプは 問題の切り分けがそもそも出来ないタイプ だからメモリリーク()に悩まされる スレッド間の協調と、メモリのケアは直交する別の話題
>>158 ちょっ漏れが作ったわけでも漏れの使い方に問題があるわけでもない階層で起きるメモリリークの責任を漏れに負わされても困る… それに他人が作ったモジュール内でのメモリリークも結局は開放が書かれていなかったか、書かれていても正しくなかったからリークしているはず… >>161 全面同意だが同意したからと言ってメモリリークがゼロになるかっていうと以下略 単純にクリティカルセクションとかキューによるシリアライズ(Active Objectパターン)で排他して マルチコアを活かさずパフォーマンスをドブに捨てて良ければ平和なんだが… だからメモリを自動開放してほしいときはスマートポインタを使えばよいだろ 循環参照が無い限りshared_ptrで問題ないだろ 循環参照がある場合はどちらかをweak_ptrにすれば済む話だろ 現実にshared_ptrの様な物が存在して無いなら、そういう議論も意味があるが 実際にはshared_ptrは現実に有るのだから、自動管理したい場合は使えばよいだけの話でしかない
むしろ議論すべきはshared_ptrのような参照カウンタ方式のスマポと 言語ビルドインのマークスイープ系のGCとで どちらが良いか、だろう 参照カウンタ方式は循環参照で問題を起こすし マークスイープ系のGCはいつ実行されるか分からない
つまり、完璧なGCは無いということだ 完璧なGCが無い以上、使う側が状況に合わせて選べた方が良いわけだが そうなるとC++/CLIのような変体言語しかないのが残念だ
このスレ論点が一致してないよね。 freeやdeleteを記述すべきという論点で話をしている人 freeやdeleteしたところでメモリが解放されてるわけではないですがという論点の人 freeやdeleteは当然、さらにnull等を記述すべきという論点で話をしている人 GCの実装そのものを論点にしている人 論点がばらっばらだから咬み合わない
>>158 > OSやライブラリにもメモリリークなんてよくあることだし よくあると言うなら10個ぐらいすぐにあげられるよな もちろん最新版でリークする奴ね MSのサイトにfix分と調査中のものが全部公開されてる。他のOSもlog、mlみれば腐るほど出てくる。 10個上げろとか、ほんと幼稚園児かよ、おまえらは。頭悪すぎw
C++でRAIIを徹底しておくのが一番いいよ 解放タイミングのコントロールが必要になったら後からでも柔軟に対応できるし GCは解放に係る少し変わった条件が発生した時に滅茶汚いことをしなきゃならなくなる
shareed_ptrはC++で比較的効率よくやれることと、GCしたい人が真にやりたいことの妥協の産物であって どんなシチュでもベストにフィットするような一押しの決定版ってほどでも無い… 参照カウンタの排他が不要で循環参照が無いことも保証できるまで設計が詰められているなら スレッドごとに、メモリを確保して使って返す処理を直に書くのが一番良い
確保/解放を直に書くのはスピード的には一番速いだろうけど解放漏れバグの温床過ぎてネ 特に例外が絡むとやってられない状況になる
>>169 > もちろん最新版でリークする奴ね 早くあげてよね w >>172 >特に例外が絡むとやってられない状況になる そこだけはstd::unique_ptr<T>の一押し これで例外状況でのRAIIが完成するので真にGCが要らんところまで逝く ていうか大概のアプリなら、例外を生じたらFatal errorなことをユーザーに知らせて終了、でいいんじゃ… >>175 いやーリソース獲得した状態でファイルI/Oとかネットワークとかが絡む場合は終了じゃすまん場合が多いでしょ 昔C言語で数珠繋ぎの独自スコープとしてblock_enter/block_leaveというのを作って { block_handle h = block_enter(b) object = block_create_object(h) block_leave(h) }
書き損じた 昔C言語で数珠繋ぎの独自スコープとしてblock_enter/block_leaveというのを作って func(b){ block_handle h = block_enter(b) object = block_create_object(h) block_leave(b, h) } というので例外にも対応したリソースマネージャ作った block_leave(b, h)せずにスコープ抜けても上位のblock_leaveで開放が保証されたり block_leave(b, 0)で全開放とかそんなの
デメリットはblock_create〜で作成するものは全部ヒープに確保されること 結局C言語でここまで必要な案件てのが回ってこなくてあんま使ってないけどリーク予防法の参考程度に
C#でアンマネージドなメモリを扱えるのはわかった 確保したメモリ領域にオブジェクトを配置する事は出来ない? C++で言うところの配置newを再現したいんだ メモリの確保解放はプログラマが特別に管理してその間は普通のオブジェクトと同じように透過的に扱いたい
>>180 例外つってるのは具体的にはSEHの話 どっかで止めた時点のblock_leave(b, h)でそれまでの開放が保証されるってこと C++にfinallyが無いのが気に食わない 今はラムダが有るのでマクロでそれっぽいものを自作したが 標準で用意しておいてほしい C++はリソースを自分で管理する傾向のある言語なのに finallyが無いのは本来おかしいよな ラッパー作ってRAIIを徹底しろってことなんだろうけど すべてのリソースに対してラッパーを用意するのは面倒だよ fainallyが有ったって邪魔になるわけでもないのに 最終的に使うかどうかは利用者が選べばよいことだし C++ってそういう言語だろ
>>183 C++にはテンプレートがあるからリソースの型をテンプレート引数とするラッパーを作るのは そんなに面倒なことじゃないと思う あとC++でRAIIを徹底してればfainallyの必要性を感じたことはない fainallyを書かなければいけない時点で危なっかしいコードだと思う むしろfinallyってデストラクタがない言語だから 必要なものなんじゃ… どうしても必要ならデストラクタで任意のラムダ呼ぶ ユーティリティクラス作れば同じこと出来るし
98以前でもローカルクラス定義できるんだからすこし冗長なだけで同じだし
例外発生はバグ、というプログラミングしかしたことないからよくは知らんが、 try { try { /*...*/ } catch (std::badalloc()) { /*...*/ } catch (UserException e) { /*...*/ } } catch (...) { // fainally節の代わり /*...*/ } じゃあいかんの?実行時コストは知らん
スマン 誤: } catch (std::badalloc()) { 正: } catch (std::badalloc e) {
デストラクタの問題点は不可視なところだな usingやfinallyは目に見えるから安心する
>>189 内側のtry〜catchから再throwするのを忘れたorz 内側のtry〜catchから再throwして外側ので再捕捉したらいいんじゃ… 例外をロジックとして使うなってばっちゃんが言ってた
>>191 throwせずにreturnするパスが有ったらどうするんだよ そういうのを防ぐためのfinallyやRAIIなのに まったくちんぷんかんぷん 結局returnする前に手動で忘れないようにthrowすることを強制するんなら goto文とか開放用ラムダ呼び出すのとかと替わらないだろ だから忘れる忘れないレベルをぶち込んでくるのは止めようやw これをぶち込むから全ての議論が池沼レベルになってる
>>194 GCなんて池沼のために生まれたようなものだし・・・ NULLったりfreeったりすることすらまともに把握、指示しきれない c++のデストラクタって後処理に失敗しても 例外投げられないからウンコ 結果的にエラーを握り潰すゴミコードを量産する原因になってる
そのクラスが管理してる範囲で後処理の失敗って何が起こるの?
現実的な確率で発生して無視出来ないリスクが有る解放処理はデストラクタでやるべきじゃない そういうリソースに対してデストラクタがやる事はプログラマに対しいて未解放のリソースを通知する事だけでよい
具体的に何があるん??? クラス内で使っているリソースで解放に失敗(失敗し続ける)するって。
どっか他のオブジェクトと共有してるものを解放しようとして失敗するとか? それはそもそもの設計に問題ありすぎだが。。
>>202 だよね。 否定しようとして無理やり現象を創りだそうとしているとしか・・・。 でもその無理やりつくった現象は、そもそも論理設計のミスが大前提だったりする。 論理設計のミスまで言われたらなんにも組めないわ。 >>200 デストラクタの中で起きた例外については try { } catch (...) { }で囲った上で、リカバリ処理(何とかしてリソース解法漏れをなくす)を行えばいいじゃない? もし例外発生後に行うべき適切なリカバリ処理が書けない(存在しない)んだとすると、 もはやデストラクタ内に限った話ではなくなって、例外を発生させた時点で設計か実装にバグが居たとしか… バグ(リソースへのポインタやハンドルを壊しちゃったとか)以外で リソース解放に失敗するケースなんて1つも思いつかない
>>206 fcloseの失敗はハンドルが正しい限りflush時のI/Oエラーの通知であって、その場合でもリソースは解放されるよ fcloseに失敗してファイルに正常に書き込みされなくてもシカトしてるんだよね? それともerrnoとかチェックしちゃってるの?
まあC++の例外を援護するつもりはないがそういう場合は 普通にフラッシュしろよ そもそもC++が二重例外時にstd::terminate呼ぶのはGCのあるなしに 関係ないからスレ違いだお前ら。よそでやれ
GCというよりライブラリとの関係だな .net framework libraryのいくつかのクラスは中で自分自身をロックするから プログラマ側で参照が切れてもGCされない
今日一日なんでFormがGCされないのか調べてて大変な思いしたわ
>>213 よくそこまで調べたな。( ・∀・)つ旦 お茶ドゾー いまだにプログラマはアセンブリ言語を使えるべきだ派?
アセンブラ知ってると知らないとじゃスキルレベル全然違うからな。話にならないぐらいのレベル差。
まあ実際Java屋とかってコンパイラやメモリ意識できない奴多いよね 以前2chで↓みたいなコードが勝手に最適化されると思って StringBuilder使う奴は馬鹿!とか言い出す奴いて目眩したわ String s; for(int i = 0; i < strarray.length; ++i){ s += strarray[i]; }
>>217 それはStringの+=の実装次第ではあんまり差が付かないケースなんじゃ… (左辺と右辺が別の実体である(アドレスが違う)ケースでは多分右辺を左辺の末尾に1回コピーするだけという実装が有り得る 真に糞なのは StringBuilder sb; String s = "Hello"; sb.Append("[" + s + "]"); が遅いからStringBuilderは糞、と結論付けるニンゲンであってコードではない、 みたいな? >>217 みたいにループ中で一個づつくっつける場合は別にして s = a + b + c + d; // このように、高々数個をくっつけてる場合は Javaだと無駄にStringBufferが作られてダメと言うのが定説だったが C#の場合は内部的にString#Concatに置き換えられて それによって StringBuilder b = 略 s = a.Append(b)中略.Append(d).ToString() するより早い、という話題があってそれと勘違いしたのかもね いちおう訂正しとこw StringBuilder sb = 略 s = sb.Append(a)中略.Append(d).ToString()
>>218 ??、これJavaだぞ。演算子オーバーロードなんて出来ないから >>219 違う違う。+の連結がStringじゃなくてStringBufferに 最適化されるらしいって話だけで、StringBulderって 必要ないでしょ?レガプロ?(笑)、って認識レベル しかもそいつ一人ならまだしもスレに同じレベルの 認識の奴結構多かったよ。レベルの低さ舐めたらあかんで >>222 実装云々でなんで演算子オーバーロードがでてくるんだ? 逆だろ? C#との勘違いでないなら、その最適化されるJVM実装とやらを示さないと
>>219 全く逆の認識してないか? classファイル解析したら分かるけど、ループ中の+=の方が問題で毎回newされるから遅い s = a + b + c + d の方は一つしかStringBuilderのインスタンスは作られない こうやって、比較的プログラミングという行為を好きでいる・好きでやっている・興味を持っているという人ですらまともに言語仕様を理解出来ていない。 malloc、freeで管理、GCで管理だと、機構の複雑さは後者。 結局GCもその機構を正しく理解しないと参照が切れてない、参照が切れていても別のリソースが・・・と。 機構を正しく理解していることが前提なら、機構はシンプルなほうがいい。 その点を誤ったから >プログラマをメモリ管理から開放する! >といいつつ、メモリリーク問題の文献が大量にある。 >これすなわち、メモリリーク問題が全然解決していないということ。 >さらに、メモリ解放のタイミングの文献まで大量に生み出した。 >これすなわち、新たなるメモリ管理に関する問題を生み出したということ。 なんてことになったんだろうね
そもそもプログラマの大半にマネージリソース、アンマネージリソースとはなに? って質問してまともに回答できる割合がどんなもんになるのか 始めたら終わらせる これワンセットね にしたほうがミスはなくなるかと ファイル開いたら閉じる メモリ確保したら解放する 通信接続したら切断する
結局いつ開放されるか分からないってのが曲者で 使い終わったら確実にリソースを開放してほしいときは 別の仕組みが必要になってしまったってのが問題だろう その別の仕組も、C++のデストラクタのようにクラスのメンバに関して 芋づる式に呼び出す仕組みがないから C++のデストラクタがやっていることを手動で再現しなければならない始末 一方でC++のスマポなどの参照カウンタ方式は循環参照だけが問題だが それ以外の問題が一切発生しない、デメリットは循環参照だけ しかも循環参照が発生する場合は片方をweak_ptrにすれば良い ということが分かりきっているし、循環参照が発生する箇所も 設計段階でわかる 循環参照に気を配れる知能が有るのであれば、参照カウンタ方式のほうがスマート
>>229 処理速度やタイミングがシビアな組み込みや科学技術計算系とかならいざしらず、 ソレ以外は、実際の解放のタイミング自体は問題にならんでしょ。(膨大なメモリの使用も別だけど) 問題は、使い終わったよーって明示しないで良い。という運用が結局、悪い結果をもたらしているという点。 メモリの管理をしっかり最後までやるクセのないプログラマは、 平然と参照が途切れている可能性のあるポイントで参照しに行こうとする。 結局は、そいつがバカだからに集約されてしまうんだけど、使い終わりの明示をしない文化がバカを生む土壌となっている そういう事になる原因ってさ、構造がぐちゃぐちゃでオブジェクト間も依存しまくって、 いつ解放していいのかわかんねえーというヘボいプログラミングなんだろうなと思う。
ある意味メモリなんて一番扱いやすいリソースだからな。 メモリの管理すら適当なプログラマが、他のリソースを適切に扱える訳がないのに、GC前提の言語ではそちらのケアが言語側でやりづらくなってしまっている。
メモリ意識した時点で雑魚プログラマ決定だろ。 JavaScriptもPascalも使えないんじゃ話にならないよ。 おちんぽ見られることを意識しすぎて温泉に入れないようなもの。 癒やしのない人生に刺激なんてない。←これ名言
>>231 そう。そういう状態にしちゃう原因が、いい加減なメモリの管理で教育された結果にあるのではないか?ということで。 >>234 だれの名言かしらんが、 刺激のない人生に癒やしはない。 ならなんかしっくりくる。まぁ逆とっても同じ意味だからいいんだけど・・・。 JavaやC#ではリソースをプログラマが管理してはいけない せっかくメモリ管理を透過的にしたのにリソース管理でコードをより複雑化させては意味がない 真っ当な教育を受けた少数のプログラマがSafeHandleを作成する 末端のプログラマはSafeHandleのファイナライザに全てを任せてメモリと同様にリソースを完全に透過的に扱うべきだ
>>230 JavaのGCでサーバー応答が止まるなんてザラにある話だよ それを聞いたことがないなら文系SEと同レベルだね >>238 管理放棄して開くだけ開いて計算資源を食い潰す玄人気取りプログラマ full GCが頻繁に生じちゃうのは明らかに設計ミスやな immutableな短命objectを使いまくるのだ。。 つかimmutableなオブジェクト使いまくるとGCないときつくね?
RAIIで事足りる immutableかどうかとGCは無関係
むしろ短命なオブジェクトなんてスタックで十分だし 管理するならshared_ptrのが優れてる
ライブラリ、アプリ、ユーザの三者で考えないと 一部リソースはユーザがを閉じることができる。 そのときアプリの参照を消す仕組みがどのライブラリにもない
>>243 よくわからんが、それは階層的におかしいのでは? ユーザーがアプリを通さずにリソースを閉じる事ができるって事? Manager.Execute((res) => ...); これが終着点 短命なリソースは全てこの形式で事足りし長命なリソースはファイナライザにでも任せればよい ユーザーが管理しちゃ絶対にダメ
このスレでGCいらんて言ってる人たちは環境に恵まれてるんだなぁって思う
参照がなくなったタイミングで必ず開放してくれて かつ 循環参照でも問題ない パーフェクトなGCが有れば最高なわけだが 実際にはそんなGCは無い となれば、通常であれば言語側は性質の異なる複数のGCを用意しておいて 使う側はシチュエーションに合わせて選べるようにしておくのが自然な発想 しかしそういう言語は殆ど無い、これが問題 といってもマークスイープ系GCが前提のC#やJavaのような言語に RAIIの発想を持ち込もうとしても C++のデストラクタのように自身のメンバのデストラクタを自動で芋づる式に呼び出す仕組みが 元々無いので、手動で芋づる式に解放関数を呼び出すコードを書かなければならなく うまく行っていない
>>246 JavaでPhantomReferenceも使ったこと無い人って恵まれてるんだなあって思う >>249 無いのでってもろにAutoCloseableとかあるやん >>250 自分のクラスがファイルなんかのcloseを持つリソースをメンバに持っていたとする そうすると、それらのメンバのリソースを明示的にcloseできるようにするために 自身もcloseを実装することになるだろう それで、自身のcloseが呼ばれた時、勝手にメンバのcloseが呼ばれるか? 結局手動でメンバのcloseを呼び出しまわるコードを書かなければならない C++のデストラクタならメンバのデストラクタが芋づる式に勝手に呼び出されるから 気にしなくて良い 強参照、ソフト参照、弱参照、ファントム参照 この字面だけで糞言語って察せられるから凄い
Rustはどう? 明文化されたmoveセマンティクスと、オブジェクトの寿命と参照のチェッカを型システムに組み込んでるおかげで、 リソース管理の実行時コストをゼロにしつつ、メモリリークが発生しないプログラムが書ける。 shared_ptrに相当するRcもあるから、所有者を複数にしたい場合のコストもそれなりに抑えられる。
rustの清貧さは好みだけどまだ触った事ないな 同期処理を省略するためかshared_ptr相当がタスク間跨げないらしいけど そこら辺の使い勝手ってどうなんだろう
>>254 難しいのは難しいが、低レベルの世界に相応な難易度であって、理不尽さはあまり無いと思う。 自分が遭遇した理不尽というか不便は、トレイト(型クラスみたいなの)を戻り値にした、ジェネリックな関数の型注釈の煩雑さで、 そのworkaroundが、その関数の返り値専用の型を定義する、ってのがカルチャーショックだった。 https://doc.rust-lang.org/std/iter/trait.Iterator.html ↑はIteratorトレイト(Listインターフェイスみたいなもの)のドキュメントだけど、mapとかfoldとかよくある高階関数の戻り値が、それ専用の型(MapとかFold)になってる。 だから、よくある関数型言語のイメージで、何か高階関数を利用したアダプタ関数を試しに定義してみよう!ってやると、 型注釈のエラー、ライフタイムのエラー等が一辺に出てきてわけが分からなくなる。 その関数の戻り値専用の型、なんて贅沢に見えるけど、返り値のサイズを見る限り、余計なデータで膨れているわけでもなかった。 Cでstruct wrap_int { int c; };とやったときにsizeof(wrap_int)がsizeof(int)と等しいけど、それと同じことをやっていた。 型情報なんてコンパイル時に全部消えちゃうから、実行コストも無いんじゃないかと今では思う。 メモリ/リソースの所有権を意識してコードを書くこと、が身について面白いよ。 ヒープを贅沢に使ってコピーしまくりなコードを書くと汚いし遅いしなんで、ちょっとダイエットする気分も出てくる。 >>251 C++もヒープ相手は自分で呼ぶので、実装は必要だよ Javaでもメンバの特定メソッド呼び出しはやろうと思えばできる 現実に横断的な呼び出しをやる場合はある 結局要求される物と実装の問題 >>255 shared_ptrと恒等なものは無いけど、ポインタ的に使える型がBox, Rc, Cell(あるいはRefCell)とあって、 Boxはヒープ領域であること、Rcは複数の所有者がいる(つまり所有者全員が死ぬまでは生きている)こと、Cellは複数の書き込みが作れること、 とか機能とコストが別れているから、これらを組み合わせて使う。 で、Thread Safetyを実現させる機構は上記には無いので、Atomicityを導入させるRcの類似形であるArcと、 書き込みもしたいならMutexっていう型も合わせて使う。 すると、例えば整数のベクトルをスレッド間で共有したい、とかになるとArc<Mutex<Vec<i32>>>という目が滑るような型表記をすることになる。 あんま詳しくないので、ケース毎にもっと簡単なやり方があるとは思うんだけどね。 >>258 ああ、Arcってのが別にいるのね。納得 個人的にもう一点気になる所があるから聞いてしまう BoxやDropを使ってるとコピー禁止になるらしいけど これ面倒な場合ない? 最初はコピー可能な型としてガンガンコピーしてたけど 途中から終了処理を書きたくなったらコピーしてる箇所 全部直すって事? ちなみにググってたらRWArcっての見つけたんだけど これ読み書き可能なArcなんじゃね >>249 javaは世代別管理でGCの種類は色々選べるはずでは >>260 起動時に切り替えられるだけであって オブジェクトごとには切り替えられないのでは >>259 コピーしまくっているような変数の型をTからBox<T>に変えた場合、確かに面倒なことになる。 けど、基本的に単純な代入(let x = y)はコピーじゃなくてmoveになるし、 Box<T>の値をコピーしてBox<T>の値を生成するっていうのは、同じヒープ領域を指すポインタを作るんじゃなく、 新しいヒープ領域を確保して中身をコピーし、そのポインタを返すという意味なんで、 変数の型を後でTをBox<T>に変える、という場面はあまり無い(少なくとも自分は学んでいる最中にそういうことをしたくなったことがない) 値をコピーする場面では、元の変数の型がBox<T>であってもTであっても、参照型&Tを受け取ってTを生成、ということをするのが定石。 &Tはほぼ無制限に安全に作ることができるし、安全じゃない可能性があったらコンパイルが通らない。 で、コピーした型Tの値は呼び出し元がBoxに包んでヒープ領域に置いたりするのが定石 Dropも別にコピーを禁止することは無いよ。後からつけたらエラーまみれ、ということにはならない。 あと、自作じゃない型に自作じゃないトレイト(インターフェイスみたいなもの)をつけることができないので、 例えば標準ライブラリのFileやTcpStreamはCopyできるようには決してできない。メモリ以外の資源管理も安全だよ。 freeし忘れるとか、そんな超ウルトラ素人ミスを大前提に議論するのは間違いだよなw freeしきれないとかwwww
>>263 規模が大きくなれば管理が難しくなるのは普通のことだよ。 ライフサイクルはオブジェクトごとに異なるものだし、 人間に頼らずにGCにメモリ管理を任せるっていうのは良いやり方だよ。 shared_ptrって参照カウント式のGCじゃないの?
循環を綺麗に扱えるなら参照カウントの方が良いと思うけど VB6は循環参照の扱いどうやってるんだろう
>>265 GCの一種だけど、文脈的にはプログラマが 管理が非局所的で明確な型宣言もなしに使えるのをGCと言ってるわけで 議論で揚げ足にしかならない野暮な突っ込みはやめようぜ >>264 いや、下手って一言で片付けられるよ。 よっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっっぽど、出ない限り 片付ける奴が馬鹿なのだ。素人ほど簡単だと言いたがり、上級者ほど簡単ではないとはっきり言うものだ。 どの分野でもな。
freeとか言ってる奴はC++使えよ。いつまでC使ってんだ。
>>270 東大生が人に教えるとき、何がわからないのかわからないというのがわからない。 上級者になればなるほど自分がやってることなんて簡単に見えてくる >>272 何が分らないか分らない、つまり東大生も生徒がどういう思考をしてるか分析できず分らないと言ってるのだ。 低学歴ほど、分らないのはおまえが馬鹿だからと簡単に片付けるものだ。 それ中級者 あと、東大生は教えるの上手いのもいるから想像で話すな馬鹿
このようにおまえのようなコンテキストすらまともに読めないPGは五万といる。 スレッドがデッドロックしてメモリを開放できないなんてよくあることだ。
>>275 俺は272に向けてたんだが そりゃコンテキスト読めてないように見えるよなw スレッドがデッドロックしたらメモリリークどころじゃないじゃないかwww
スレッドがデッドロックしちゃってメモリ解放できない(泣) っていうPGが五万といるのかよw
まぁfreeやdeleteやnullやらすらできないPGに、「僕はそんなこと管理しきれる脳みそ持ってない!」って言われたらソレは真実なんだろうけど・・・。 そんな脳みそPGに「もっと複雑な業務使用」を理解できるとは思えないんだ。 そんなPGにプログラミングの場を与えるのが間違い。
そもそも実務でスレッド使うPGなんてゴマンもいない
Javaのプロジェクトだとほぼ使ってるけどな隠蔽してるだけで そのせいで共有リソース壊したり、逆に個人情報の領域が共有されたりして、とんでもないインシデントが発生する そんな奴等にメモリ管理なんて任せられんし、共有リソースも触らせたくないから 更に隠蔽したフレームワークもどきが出来上がる
>>282 勝手に使うな。勝手にトリッキーコードにすんな。 素直に、設計書通りに作れ。 勝手なことやって勝手に自爆してるだけじゃねーか。 javaってc++のconst参照に対応するものが無いのに、素人みたいなプログラマを大量にかき集めているのが怖すぎる。
>>283 理解してないのに無理してレスしなくていいから C#はマルチスレッド使いまくりだけど事故の話はあまり聞かないな マイクロソフトが優秀なのか低品質プログラマがいないのか
Freeし忘れ ↑これ。 ソースコード書いてる人間の注意力次第でバグが入るなら 言語も設計も間違ってるよ
動的型言語 ↑ これ コード書いている人間の注意力次第でtypoするだけで 実行するまでわからないバグが入るなら 言語も設計も間違ってるよ
C#でcatchやfinally書くの嫌すぎる C++に戻りたい
COMのVariantとかJSとかリークしまくりだし
そういやVBScriptって参照カウンタ以外のGC積んでんのあれ 必要には見えないんだけど
解放処理 すら、まともにお前ら管理できねーのかよ・・・・・・・・・・・・・・・・。そらオレが完璧な仕様書渡してもバグってるわけだ
開放処理を手動でやれって書いてある仕様書かw 御免こうむるwwwww
ガベコレのあるPyObjectをラップするクラスをガベコレのあるDで書いたら wxPythonで書いたクラスをDから使ったとき意味不明なタイミングで落ちるようになった 二重に管理するとだめなんかな
ガベージコレクションはたしかに便利だ だからといって「本来はてめぇのケツはてめぇで拭け=自分で解放すること」を忘れてはならない そんだけ
C#ではSafeHandleだけ作って後は放置 usingも使わないってのがトレンドだけどね 自分で解放とかバカバカしい 面倒はランタイムに見させて開発者はドメイン設計に集中するって目的を見失うな
>>303 オブジェクトの開放を他と独立にやれるケースばかりならそう言えるかもしれんが オブジェクトAとBがリソースCに依存しているケースでA、Bの開放の少なくとも片方をGCに任せる場合、 リソースCの参照カウンタなりをつかった防護策をプログラマーが書かねばならない しかしそんな嫌ったらしい雑用を増やすぐらいなら Cオープン A生成 B生成 A, B使用 B開放 A開放 Cクローズ でええやん? さらにダンプファイルとかからの障害解析において、オブジェクトが生きているべきなのか死んでいるべきなのか決まっていないとか、 アドレスがはっきりしないとか言う状況は地獄 つかこの世はうつろうもののであって、物理的ハードウェアでプログラムを実行する限り、 計算モデルは明らかに状態遷移ベース(チューリングマシン)の方に分がある GCとかチューリングマシンで無理矢理関数型プログラミングを行うためのつなぎの技術、 いわば邪道 どんだけ蛇が出てくるか、GCの方がかえってわからん
>>304 設計が悪い 使い終わったという言葉が示す通り使い終わったならどうなろうが知った事ではない 知らなきゃ困るような設計にしたのが間違いだね メモリ空間は無限であるべき 使い終わったメモリの断片化なにそれ? 仮想メモリを管理するのはCPUの責任だろ
>>306 >>304 の例で、さらにCを上書き更新したいオブジェクトDがいたらどうすんの? GCがA、B両方開放してくれるまでDは期限不定で待たされるけどそれが>>306 的に良い設計なの? つまり、ハードウェアリソースの有限性を考慮する限り >使い終わったという言葉が示す通り使い終わったならどうなろうが知った事ではない が常に成立はしないという話 >>308 そんなあっちこっちから同時にリソース掴みに行く設計が悪いって最初からわかってて言ってるんだろ? 意見を否定するためだけの極端な反例(この場合は例にすらなっていないが)を引き合いに出すのは不毛だよ >>309 >そんなあっちこっちから同時にリソース掴みに行く設計が悪いって最初からわかってて言ってるんだろ? 極論なもんカヨ; 例: 表示デバイスの数>表示したいスレッドの数 というのはざらにある で、>>308 のオブジェクトDのケースはどう解決すんのさ… GCが「いつ開放してくれるかわからない」ブツである以上解消しない問題だとおもうんだけど (A、BにCのための明示的closeメソッドを付けるぐらいならGCに頼らずに順序管理するわ; 解決策の一つはActive ObjectパターンでリソースCの管理を1スレッドXにやらせて Cに対する要求を全部Xのキューにシリアル化して入れさせるというのがあるが、それはそれで リソースCを使う全てのオブジェクトがスレッドXに依存するから、Xの開放コードが面倒なことになりかねない かつ、シリアル化はマルチコア時代のせっかくの並列実行性能を殺してしまう GCに合わせて生きることは、神仙にでもならねば到底かなわぬ…
>>311 その例じゃ308の状況にならないよ どんなコード書いてんだよw >>314 >その例じゃ308の状況にならないよ なんで?ビデオメモリに2スレッドから同時に書いて無事に済むと思ってるの…; だから同時に書く設計が悪いんだって 気合入れて設計を見直してみろ そんな必要はないってわかるから
ていうか>>316 の言っていることはますます矛盾で、 >同時に書く設計が悪い >そんな必要はないってわかる というのは明白に「書き込みの順序を設計できる」ということを言っていて、 それはその通り(チューリングマシンの計算モデルに合致する)ので別段漏れの立場と対立するものではなく、 かつ気合を入れて設計すれば順序で全て解決する(GCは不要である)という言明でもある >>315 もはやGCがどう関係するのかわからない >>318 彼は敵対意見に反論する材料が欲しいというだけで変な例をでっち上げて出してしまったんだ 本人も今頃困ってるんじゃないかな >>319 >>308 を変な例変な例というばかりでGCを用いた正しい解決方法が一向に示されない件について: 繰り返しになるが、>>308 のオブジェクトDのケースはどう解決すんのさ… たとえ変でも反例は反例だし >>308 のリソースCがファイルなのだとしたら、病的な反例というほど例外的想定でもない 読み書き順序の設計の必要性(破壊的代入前提のプログラミング)を口にしつつ >使い終わったという言葉が示す通り使い終わったならどうなろうが知った事ではない (>306) と言い切ることはできないとかそういう話 で、現実のハードウェアは破壊的代入前提のブツばかりであるという、(>306) >>318 ウィンドウシステムでの描画は一般に裏VRAMに描いてハードウェアでBitBlt転送するが 裏VRAMに書く際のデバイスコンテキストが複数使えるが数に限りがある場合… とか細かい話をしても通じないようならリソースCをファイルと考えてくんな プチ訂正 誤: で、現実のハードウェアは破壊的代入前提のブツばかりであるという、(>306) 正: で、現実のハードウェアは破壊的代入前提のブツばかりであるという、(>308)
読み込みと書き込みを別のリソースに分離したり読み書きが同時に出来るように作る 書き込みたいから読み込み終わるの待ってますってリソースの無駄だろ
なんか参照カウントの話とマルチスレッドの話がごっちゃになってね?
>>322 >読み込みと書き込みを別のリソースに分離したり読み書きが同時に出来るように作る 破壊的代入の世界ではそいつは常に可能とは限らない >308の例で、リソースCがファイルXなのだとしたら、オブジェクトDが上書きすべきもあくまでファイルXでないといけない。 つまりリソース分離の余地など無い (正確には、無理矢理ファイルA、BはファイルX、DはファイルYに分ける設計もありえるが、XとYに対する変更をいつどのように統合するかという超難題が生じる この手の混乱は、A、BがアクセスするリソースCの開放タイミングの決定をGCに任せてサボったがために生じるのである おいおい、バージョン管理のマージの話にまで拡張したら収集つかなくなるぞw
>>324 ファイルの分割は必ずしも必要ではないし更新モデルから読み取りモデルへの同期も必要ないよ メモリ管理もできないんだから データの依存関係とか関係ねえ〜〜〜〜〜〜〜〜〜〜〜〜 でおわりでは
GoogleChrome動作中のタスクマネージャーのイメージ名にsvchost.exeが見当たらない GoogleChromeでは、svchost.exeを使用せずに、chrome.exe自身で制御しているらしい Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36 Width/1360px/1920px
メインメモリに対するGC・・・MGC HDDならストレージGC・・・SGC
GoogleChromeかsvchost.exeを使わなくなった理由・・・ページメモリGC制御が遅過ぎでお粗末だからか?
GoogleChrome動作中のタスクマネージャーのイメージ名にsvchost.exeが見当たらない GoogleChromeでは、svchost.exeを使用せずに、chrome.exe自身で制御しているらしい Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36 Width/1360px/1920px
そろそろsvchost.exeを使うソフトは使用禁止なのかも?
svchost.exeを使わないことでGoogleChromeは確実に応答性能が速くなっている ・・・動画マルチ再生でクラッシュしたFirefoxは見習うべき
残念だがスリープだ! 京がお仕置き候補に??? http://gigazine.net/news/20130618-fastest-supercomputers/ ◆1位:Tianhe-2(天河二号)、中国人民解放軍国防科学技術大学 IntelのIvy Bridge(12コア・2.2GHz)とXeon Phi(57コア・1.1GHz)を採用し、 コア数は312万、計算速度は33.9ペタフロップス、消費電力は17.8MW ◆2位:Titan、アメリカのオークリッジ国立研究所 AMD Opteron 6274(16コア・2.2GHz)とNvidia Kepler(14コア・0.732GHz)を採用し、 コア数は56万640、計算速度は17.6ペタフロップス、消費電力は8.3MW ◆3位:Sequoia、アメリカのローレンス・リバモア国立研究所 IBM BlueGene/Qを採用し、中のプロセッサーはPower BQC(16コア・1.60GHz)、 コア数は157万2864、計算速度は17.2ペタフロップス、消費電力は7.9MW ◆4位:スーパーコンピュータ京、独立行政法人理化学研究所 計算科学研究機構(AICS) 富士通 SPARC64 VIIIfx(8コア・2.0GHz)を採用し、コア数は70万5204、 計算速度は10.5ペタフロップス、消費電力は12.7MW ◆5位:Mira、アメリカのアルゴンヌ国立研究所のエネルギー部門 BM BlueGene/Qを採用し、中のプロセッサーはPower BQC(16コア・1.60GHz)、 コア数は78万6432、計算速度は8.6ペタフロップス、消費電力は3.95MW 気づかないかISOは中国のためにある >>344 蓮舫さんに次の選挙は次点で良いですよねって言ってきて ただしChromeはプロセスが一杯できるから タスクマネージャ覗いた時に気持ち悪い
64の時代だから、そろそろCore64ぐらいでイイのでは? diginnos stickpc_02 VIDEO &list=RDOPt0OGNQhnU 723 : 名無しさん@お腹いっぱい。 2016/01/10(日) 12:24:00.06 ID:rlcuxF0A0 Vivaldiの起動が遅いのは タブのサムネイルに関係しているかもしれない Blinkは負荷分散のため?かHDDアクセスも遅いらしい ローカルストレージ関係がとても遅いからだ 724 : 名無しさん@お腹いっぱい。 2016/01/10(日) 12:31:29.50 ID:rlcuxF0A0 タブサムネイルを ローカルストレージで保存するのは止めたほうがいい タブサムネイルは直接アクセスする事 fopen();ランダム書込:fclose();ランダム読込:fopen(); 読取だけならオーバーヘッドを避けるためfopen();しない 725 : 名無しさん@お腹いっぱい。 2016/01/10(日) 12:33:41.35 ID:rlcuxF0A0 命題・・・Vivaldiは遅い起動を早期解消せよ! 726 : 名無しさん@お腹いっぱい。 2016/01/10(日) 12:37:50.17 ID:rlcuxF0A0 ランダム書込用HDDスペースを作る 個数*固定サイズ 1トランザクション 個数1024個、固定サイズ256kバイト 727 : 名無しさん@お腹いっぱい。 2016/01/10(日) 12:40:34.65 ID:rlcuxF0A0 そしたら、ランダム読み書きでfopen()すればいい オーバーヘッドを避けるためfopen();は終了のときだけ オーバーヘッド無いだけで1000倍ほど速くなるケースも 728 : 名無しさん@お腹いっぱい。 2016/01/10(日) 12:44:26.42 ID:rlcuxF0A0 オーバーヘッドはドコにあるのか? それはWindowsOSのフォルダ構造検索にある フォルダ構造検索回数を省けば速くなるのだ
Vivaldiの起動が遅いのは タブのサムネイルに関係しているかもしれない Blinkは負荷分散のため?かHDDアクセスも遅いらしい ローカルストレージ関係がとても遅いからだ タブサムネイルを ローカルストレージで保存するのは止めたほうがいい タブサムネイルは直接アクセスする事 fopen();ランダム書込:fclose();ランダム読込:fopen(); 読取だけならオーバーヘッドを避けるためfopen();しない 命題・・・Vivaldiは遅い起動を早期解消せよ! ランダム書込用HDDスペースを作る 個数*固定サイズ 1トランザクション 個数1024個、固定サイズ256kバイト そしたら、ランダム読み書きでfopen()すればいい オーバーヘッドを避けるためfopen();は終了のときだけ オーバーヘッド無いだけで1000倍ほど速くなるケースも オーバーヘッドはドコにあるのか? それはWindowsOSのフォルダ構造検索にある フォルダ構造検索回数を省けば速くなるのだ
やっとこの気色の悪い仕組みにトドメが刺されたか javaとかGCが基本だけどflash();とかできるの?
GCのすべてを否定するつもりはないけど・・・ GCはメモリ管理を自動化する技術だけど、今のコンピュータはメインメモリを何十ギガ積んでたりするのも普通で メインメモリが足りなくなることはほぼ無くて、しかも仮想メモリもあるから、なおさらメモリは潤沢で・・・ むしろメインメモリ以外のリソースの方が余程貴重で、もし仮にメインメモリが足りなくなるまで GCを発動しないアホなGCが有ったとしたらメインメモリより先に他のリソースが枯渇する状況 だからメインメモリは無駄遣いしてもよいけど、他のリソースは使い終わったら こまめに開放しないとダメだから、いつ実行されるか分からないマークスイープ系GCの余計にRAIIな仕組みも必要なわけ しかしこのRAIIが付け焼刃でなまっちょろい出来だったりする C#で言えばDisposeが有るけど、C++のデストラクタのように特別扱いされておらず ただの普通の関数でしかないので、C++のデストラクタみたいに自身のメンバ変数について 自動で芋づる式に呼び出してくれない だから手動でメンバのDisposeを芋づる式に呼び出すコードを記述しなければならない いちいち自身のメンバ変数にIDisposableなものが有るか無いか調べるのもひと手間かかるし もしそうだったら自身もIDisposableにする必要があり、例の一連のイディオムを書かなければならない 当たり前にDisposeの呼び出し忘れが有ってもいけない まるで、mallocしたらfreeするのと似ている しかもIDisposableはコンポジションで増殖する IDisposableなオブジェクトをコンポジションしたら、自身もIDisposableといった具合 C#のようにコンパイラマジックでなんでも実現する言語で どうしてDisposeをC++のデストラクタみたいに特別扱いしなかったのか謎だ
謎だといったが、理由ははっきりしていて メンバのDisposableを自動で呼び出す為には 他で使われてないことを保証する必要があって 参照カウンタ方式のようにローコストなものなら簡単に分かるが これでは循環参照の問題が出る プログラマが循環参照を気にしなくてもよいことが前提の マークスイープ系のGCを搭載した言語では設計思想が破たんするので 参照カウンタ方式は採用できないし マークスイープ系GCでは何処からも参照されていないことがローコストに分からないので 自動でDisposeを呼び出す仕組みを用意できない どうにもならない 結局C++の方式が一番優れている 循環参照が発生する場合はweak_ptrを使う事だけ注意を払えば GCにまつわる他の問題が一切発生しない
もっと言えばC#でDisposeを実装する場合でも↑は問題になる 自身のメンバのDisposeを呼んでよいのかどうなのか 完全に自分しか使ってないことが分かっているのであればDisposeを呼び出して問題ないが あちこちから参照されている可能性があるメンバなら勝手にDisposeを呼び出してはいけない GC任せにするか、自分で参照カウンタを実装するか どちらにせよ、RAIIと相性が悪い
前から何度も言ってるがDisposeの実装はしていいが呼び出しは禁止 これがC#では基本だからね リソースの使用効率が悪いとか軟弱な反論をするバカがたまにいるが 実行効率気にするならそもそも別の言語使えって話になるからな C++CLIを使えってこった 本質を見誤るなよ
c#の欠点はデストラクタが呼び出されるタイミングが分からないこと。 不便で仕方ないや。
最近VB.NETを使い始めたんだけど new したオブジェクトが不要になった時にDispose()よんだり参照にNothing代入する必要ってない(やってもいいが無意味・無駄)なのかな?
c++のデストラクタは例外投げられないウンコ仕様 だから皆デストラクタ内で発生したエラーは握り潰してる 他の言語はあんなバカなの真似する必要ない
javaはファイナライザで発生した例外は握りつぶすことが仕様で決まっているな。 c++の場合は、デストラクタでどうしても例外を外に伝えたかったらやりようはある。
そら伝えたかったらやりようはいくらでもあるでしょう?C++に限らず
Javaは強制的に解放させることもできるようにすべきだったな。
Java(VM)は(すべてのプラットフォームで)強制的に解放させることもできるようにすべきだったな。
都度メモリ管理するよか、GCに任せた方がスループット的に有利な場合も多いでしょ。
GCはメモリ管理に関しては成功してる、 でも、メモリブロックをオブジェクトに昇格させたにも関わらず、相変わらず「メモリ管理」だから失敗。
そうそう、メインメモリの管理に関しては100%成功している しかし、今やメインメモリはそれほど貴重なものではないわけだがな コンシューマでも数十GB積んでたりは珍しくない メインメモリがなくなるより他のリソースが枯渇する方が現実的 だからメインメモリ以外のリソースに関しては使い終わったら即座に開放してほしいから GCとは別にRAIIを行う仕組みを導入するわけだが 真剣に考えていくと、RAIIはGCと相性が悪い そもそも使い終わったら自動で即座に開放(RAII)できるなら全てのGCはそう実装すべきで それが出来ないからわざわざコストのかかるマークスイープを遅延して実行しているわけだからな C++みたいにGCを参照カウンタ方式にして、プログラマが人力で循環参照が無いことを保証する以外に あちこちから参照されるオブジェクトのRAIIを自動化する方法は無い
簡単だよ スレッド立ててGCをフルサイクル実行し続けるだけ
javaもsandy-bridge以降でSSDとかならそれほど重いってわけじゃないけど 相変わらずatomでeMMCだったりする環境も並行して存在してて そこで動かすと改めて糞だと思うわけよ GCが悪いんじゃなくてjavaランタイムが悪いんだろうけどね
フラッシュとJAVAは、システムに見つかり次第、速攻アンインストールしている
>>377 Pythonみたいに参照カウント+GC(循環参照を解放するため)が最強ってこと? 最近のPC環境でも贅沢が過ぎるプログラムは動かん。 最近の奴だと、Node.jsのパッケージマネージャnpmが`npm search`と初回に打つとパッケージ検索用のインデックスを作ろうとするんだけど、 1つのjsonオブジェクトにまとめようとするからかOOMエラーを吐いて失敗するっていう不具合。 npmに登録されてるパッケージ数が膨大になったせいもあるが、設計を間違えると遅いどころか動かなくなる。
GCがある言語でRAIIみたいな事したいのなら loan patten使えばいいだけでは
リソースを共有した上で最後の参照が切れた時点で回収してほしい しかし誰が共有するかもその寿命も実行時までわからない そういう前時代的なダサい設計をした時の話しなんだろ Loan Patternはこの状況では役に立たない
しかし、言語側は、そういうダサい設計も許さないといけないので マークスイープ系GC搭載で、循環参照が有っても良いことが前提になっている言語で 「使い終わったら自動で即座に開放」を実現するのは困難 そんなことが可能なら、マークスイープは要らないからな
循環参照なんて放置すればいいの どうせプロセスが終了すればOSが開放してくれるの
>>387 Windowsのように定期的に再起動しなければいけないソフトウェアができあがっちゃいそう 常識的に考えてカーネルの実装にはGCなんて使えないし 業務アプリケーションではパフォーマンスより開発速度がはるかに重要になる 結局適材適所だ GCを強制されるのは苦痛だが使えないのも苦痛だ 好きな時に使える言語がいいよね!
パフォーマンスが問題にならないGCが一つだけあって、それが参照カウンタ方式のGC パフォーマンスが問題にならない→即座に逐一削除できる→RAIIが出来る 非常に強力だがプログラマが循環参照が無いことを保証しなければならない しかし、循環参照が発生する場合は設計段階で分かるのでそれほど深刻では無いのだ!
androidでもう何も判らん状態でプログラミングして それなりに動くのができたからおれは許したよ でもサービスまで勝手に回収されちゃうとは思わなかったわ アホだろグーグル
RAIIに必要なのはデストラクタが呼ばれることであって実際にメモリが解放されることじゃないから GC言語でもRAIIができないわけじゃない。
RAIIに必要なのは適切なタイミングで確実に解放処理が呼ばれることであって いつ呼ばれるかわからないデストラクタではだめ
かつてStandard MLの実装で、GCじゃないメモリ管理方法をやってみたのがあったな。 コンパイラが全部自動でやるからコードの見た目はSMLなんだけど、いざ動かすとGCより遅かった。 ある程度プログラマがリソース管理のためのヒントを与えないと、GCを捨てられない。
>>396 おまえが言っているのはファイナライザ。 それと、デストラクタはメモリの解放なんかしないよ。デストラクトするだけ。 この際、呼び名はどうでも良い 参照カウンタ方式以外のGCでは、どこからも参照されなくなったことが、即座にはわからない だから、自動で即座に開放関数を呼び出すことが出来ない→RAIIが出来ない C#で言うところのusingみたいに、プログラマが手動で情報を与えるなら出来る だが、usingはGCでは無い
>>393 間違い マークスイープのように負荷が集中しないだけでありパフォーマンスへの影響はある 特にツリー状のデータついてルートが削除された時子要素もデクリメントする必要があるため負荷が大きい カウンタはオブジェクト毎に持つためコピーオンライトとの相性が悪い また言語の機能として実装されなければ明示的に行う必要がある(例えばCとか) そのためgcない言語ではマークスイープと比べ非常に面倒なことになる androidで原因不明のフリーズが発生、プロジェクトはデスマーチに突入した これだからGCは
>>401 そりゃどんなものだって多少の負荷は有るよ しかし参照カウンタの上げ下げの負荷なんか マークスイープに比べれば無いも同然 マルチスレッド環境だと参照カウンタとかいうクソアルゴリズムは使い物にならない
>>407 確かに現実的にオーバーフローしないと言えると思うけど STLとかもそういう実装になってる? 使う側は少なくとも1つのポインタを持たなくちゃいけないんだからオーバーフローし得ないだろ
マルチスレッドでGCスレッド立ち上げて、再配置起こる可能性のある普通のGCだと、オブジェクト毎にLock,Unlockできる何らかの機構が必要だし、参照カウンタ増減するより高頻度でその機構使うよね。
例えばWindowsだとInterlocked系のAPIを使えば マルチスレッドでも安全に参照カウンタを増減できるから パフォーマンスは何の問題もない
C#なら参照のコピーはただのワード代入で済む メモリ確保もポインタへの加算だけで済むから圧倒的に速い 回収もマルチスレッドで処理されるから圧縮フェーズ以外はUIへの影響もなくユーザ目線では実質コストゼロ 良いコードを書いてるなら圧縮もたまにしか起こらないし起こっても大した事ない
>>399 からの流れを見ればわかるがそういう話ではない 参照カウンタ方式以外のGCは、オブジェクトがどこからも参照されなくなったことが「即座」にわからない だからRAIIが出来ない、そういう話 もちろん、参照の値が書き換わるたびに毎回マークスイープを実行すれば 即座にゴミが分かるがのでRAII出来るが、マークスイープは重いので参照が書き換わるたびに毎回実行できない その意味で、循環参照以外のGCは重いと言っている 参照カウンタ方式は軽いので毎回実行できる 即座にゴミが分かるからRAIIが出来る 参照カウンタ方式で問題になるのは循環参照が起こった場合だが 循環参照が発生する箇所は設計段階で分かるので、実際には大した問題ではない C++であれば、片方をweak_ptrにすればよいというだけの話 そこさえ気を付ければ、参照カウンタ方式とデストラクタの組み合わせは非常にうまく機能する IDisposableのようなものも要らない >循環参照以外のGCは重いと言っている ↑間違えた 参照カウンタ方式以外のGCは重いと言っている
>>413 安全が何で保証されてるのかを知るためにアセンブラを勉強しなさい。 その上で「パフォーマンスは何の問題もない」かどうかを語りなさい。 前にも書いたが、RAIIとGCは直接の関係はないよ。 現にC++/CLIでは、ローカルスコープのオブジェクトがスコープを抜けた時点、あるいは gcnewで作成されたオブジェクトがdeleteされた時点で即座にデストラクタが実行されて メモリの回収自体はGCで行われる。
>>415 そもそも不可視のコードでリソースを解放するのが愚行そのもの プログラマとしての良識があるならusingを使いなさい RAIIなどというくだらないバッドノウハウはC#では必要ない >ローカルスコープのオブジェクトがスコープを抜けた時点、あるいは >gcnewで作成されたオブジェクトがdeleteされた時点で即座にデストラクタが実行されて >メモリの回収自体はGCで行われる。 それはGC関係ないRAIIの話だろ C#でもusing使えばRAII出来るが usingも、ローカル変数も、deleteも、何れもGCじゃない 手動で寿命管理しているに過ぎない 寿命管理を自動化(GC)しつつ、RAIIを実現する話をしているわけだが どんな場合でも、GCで有ろうが無かろうが、手動でデストラクタなりファイナライザなり呼び出せば RAII出来るに決まっているだろ、それに何の意味が有るんだよ 自動化の話だよ
>そもそも不可視のコードでリソースを解放するのが愚行そのもの その最たるものが、マークスイープ系GCなわけですが いつ実行されるかすら分からない まさに不可視
極端な話 mallocして使い終わったらfreeして はい、手動でRAII出来ました!って主張 それ何の意味が有る話なの?ってね
>>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の有無に直接の関係はない。 メモリとその他のリソースを混同して考えるからダメ まずその他のリソースは不可視のコードで解放しちゃダメ リソースのスコープは明示的でなければならない これはデストラクタにもGCにも任せられない 逆にメモリは不可視のコードで解放してもよい まずこの基本原則から話を進めよう
schemeにはdynamic-windみたいな他所に継続が飛んでも後処理が保証される仕掛けがあるし デストラクタがない==RAIIできないにはならないと思うの・・・
>>424 んな事はない。 あらゆるリソースの寿命はライブラリでデフォルトの管理がされるべきであり、使用者の完全性を前提にすべきではない。 >>426 銀の弾丸は無い あらゆるリソースのあらゆる利用形態に対してデフォルトの動作を定義できるなら話は別だが無理だよね 結局は人が方針を決めて書くしか無い 幸いにしてメインメモリにはRAIIやマークスイープという正解が見つかっているのでそれを使えばいい だが他のリソースはダメだ >>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はともかく、デストラクタでもダメって意味不明すぎるんだが 考えの根本がおかしい 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のような冗長なコードを書く必要もない
訂正 struct A{ *obj }; void func() { A a; } ↓ struct A{ object *obj }; void func() { A a; }
結局、C#のDisposeはどこまで行ってもどんなに進化しても手動で書かなければならない 自身のDisposeが呼ばれたからと言って、自身のメンバ変数のDisposeを芋づる式に勝手に呼び出して良いかは コンパイラにはまったく判断が付かない 他からも参照されていて今まさに使われている可能性がある以上 コンパイラが勝手に自動でDisposeを呼び出すコードを生成することはできない GCを発動してみるまでは、どこからも参照されなくなったことが保証できない しかし、GCの発動まで開放が遅延しても良いのであれば、そもそもDisposeは要らないわけで Disposeの実行はGC発動より先行していなければならず、GCに頼れないということになる なので、自身のDisposeが呼ばれたときに、自身のメンバのDisposeをしてよいかは プログラマが考え、手動で呼び出す必要が有る 所有権が単一であれば、手動でメンバのDisposeを呼び出せばよい 手動で記述しなければならないので面倒くさいし、ミスの元ではあるが、一応できる 所有権が複数であれば参照カウンタを使うしか現実的な方法は無いだろう マークスイープ系GCなのに参照カウンタで独自に管理するのは馬鹿げているがな 参照カウンタ方式+デストラクタ であればこれらの問題は一切発生しない 参照カウンタが0になったことは即座にわかるし、デストラクタはメンバ変数に対して芋づる式に呼び出されるので 開放に関しての特別なコードを手動で書く必要は無い 開放処理も一本化される
>>428 バカすぎる 細かい事気にせずデストラクタで解放すりゃそれでおkって感じの適当な現場でしか働いた事無いんだろうな ポインタがメンバ変数になってたら公開しちゃいかんでしょ
まずDisposeは生成できる めんどくさいという奴は知識が無いだけ リソースを共有する事は少ない というか設計段階で可能な限り少なくする そして共有するならするでしっかり管理して自動解放などという手抜きはしない 基本中の基本だ
デストラクタで解放してはいけないリソースをデストラクタで解放しなければいいだけで、デストラクタで解放すればいいリソースはデストラクタで自動的に解放すべき。
>参照カウンタ方式+デストラクタ >であればこれらの問題は一切発生しない .NETのマーク&スイープGCの上でRAIIを実現している実例としてC++/CLIを説明したんだが、 「基本的なこと」とか言いながら結局何も理解してないんだな。 そもそもRAIIの話で所有権が共有されたオブジェクトを持ち出すのが意味不明すぎる。 >参照カウンタが0になったことは即座にわかるし、 「いつか」全員が所有権を手放したら「即座に」破棄される 「いつか」全員が所有権を手放したら「いつか」GCで破棄される どう違うというのか。
RAII信者の痛さは異常 オブジェクトをコピーされたら破綻するのに
グローバルインスタンスホルダーは明確にインスタンスの状態を把握したいときに積極的に使うべき
>「いつか」全員が所有権を手放したら「即座に」破棄される >「いつか」全員が所有権を手放したら「いつか」GCで破棄される >どう違うというのか。 少なくとも最善が尽くされるという意味で違うし 同じデータと同じプログラムで有れば、常に同じタイミングで開放処理が走るという再現性が有る それから、自分しか所有権を持っていない場合、つまり参照数が常に1というシンプルな状況ですら 参照カウンタ方式の方が開放処理が自動化されて楽 参照カウンタ方式で有れば、スマポを使っておけば済む scoped_ptrでも良い マークスイープ系GCであれば、自身しか所有権を持たない単純な場合でも 非常に面倒なことになる 自身にDisposeを実装して自身のメンバのDisposeを呼び出すコードを手動で書かなければならない 何故こういったコードをコンパイラが自動生成できず、手動で書かなければならないのかの根底に まさにマークスイープGCの存在が有る マークスイープ系GCは何処からも参照されなくなったことがその場ですぐに分からない GCを発動してみるまで保証することが出来ない 自分のDisposeが呼び出された、まさにその瞬間に、自分のメンバに対してもDisposeしてよいのかどうなのか 参照数がリアルタイムで即座に分からないので判断する材料が何も無く コンパイラはC++のデストラクタのように自動で芋づる式に開放処理を呼び出すコードを生成することが出来ない 要するにマークスイープ系GCではDisposeのコンパイラによる自動生成が出来ないという大きなマイナスが有る
>>440 子要素をDisposeしていいかどうかもわからないってそりゃ設計サボってる以外のなんでもないだろう ちゃんと設計してればいつ削除してよいかなんてわかるはずだろ まともに設計もできないレガシーエンジニアは黙っててよ 設計に時間使わないとリソース云々以前に別のバグだらけになるぞ メンバにDispose持たせる設計って大抵ダメだよね
>>440 前者(参照カウントGC)はRAIIができるが後者(マーク&スイープGC)ではできないというお前の 主張について言っているんだが? 「最善が尽くされる」からRAIIができて、尽くされないからRAIIができないとでも言うのだろうかw >要するにマークスイープ系GCではDisposeのコンパイラによる自動生成が出来ないという大きなマイナスが有る 何度も例に挙げているC++/CLIでは、デストラクタを記述するとコンパイラによってDisposeが追加される。 そして、ローカルスコープに置いたオブジェクトに対してはスコープを抜ける際に自動的にdeleteが呼ばれる。 そこからdelete→Dispose→デストラクタと呼び出される。RAIIに必要なものは揃っているし、事実、可能だ。 もちろん、そのメモリ領域は別のタイミングでGCによって回収される。 ここまで説明しても理解できない低脳ならしょうがない。 やはりデストラクタとファイナライザの違いが理解できてないようだからそこから勉強しなおせ。 { std::shared_ptr<my_namespace::my_class> p(new my_namespace::my_class(...)); /* unko_code */ } using(var obj = new MyClass(...)) { /* GoodCode */ } 美しいという事はいい事だね C#は書いてある事がシンタックス的にもセマンティック的にも明確だ リソース管理はこうでなければならない
>>447 C++にもusing使えやw いらない波括弧外せやw >>447 usingの方が全然明確だね objがコピーされてても問題ない RAII脳ではわからないんだろう schemeに何十年も前から存在するwith-xxxx 系を一般化した構文だね
アレを更にtypedefされたりされると ワケワカランくなるよな
c++なら普通こうだな { my_class obj(...); ... } そういやc#でp.release()相当の事って簡単にできるの? { auto p(make_unique<my_class>(...)); ... } nullって代入可能?
GCがあるのになぜJavaはメモリリークしまくるソフトウェアを量産するのか
GC大好きっ子に聞きたいんだが 完璧な(理想的な)GCを搭載したメジャーな言語処理系って何があるの? これで開発すればリークも管理も気にしないでOKってやつ
無い マークスイープ系GC → 循環参照OK、しかし即座に開放されない 参照カウンタGC → 即座に開放される、しかし循環参照NG ということで、理想のGCは無い 全てのGCは何かを妥協している それから、たとえGCを使ったとしても 要らなくなったオブジェクトの参照をいつまでも握っている奴が居たら解放されないから リソースの管理をしなくてよいということは無い あと、GCは基本的にメインメモリに対してしか有効に機能しないから 例えばファイルオブジェクトなんかは要らなくなったら即座にcloseするなりすべきで リソース管理フリーというわけにはいかない
つまりは、GCを使っていたとしても 君がオブジェクトを何処かに登録したなら オブジェクトが要らなくなったら登録解除してあげないと そのオブジェクトは解放されないのだ これはちょうどmallocしたらfreeしましょうに似ていて GCを使ったとしても全てのリソースの管理が自動になるわけではないということだね 究極的にはGCの利点は自分でfree/deleteをしなくても良いところにある これはつまり、ダングリングポインタが発生しないということだ
そして無視されてしまうコピーGC君 GCの利点は自分で大量にメモリの確保&解放するプログラムにおいてバグが出にくくスループットも出るってところだと思う もしheapをそんなに頻繁に確保&解放しないんだったらGCない言語の方がいい ただ近代的な言語は少数の例外を除いて大抵GC積んでるけど
>リソース管理フリーというわけにはいかない リソース管理フリーについてはrustみたいなGCない言語のほうが達成できてるよね(あとは関数型言語か) でもrustでもリソースの解放時にエラーを吐く可能性がある処理なら自分で解放する処理書かなきゃいけないっぽいけど
RAIIでも結局どのタイミングで解放されるか意識しなくてもいいってわけじゃないし リソース解放処理を書かなくていいだけで
メモリ管理系のバグが顕在化しにくいだけで、そこら辺適当なまま中途半端にキャリアを積む開発者を量産するという害悪が大きい。 JNIやらで他のAPI使う必要が出てくると結局いろいろ配慮しなきゃいけなくなるし。
>メモリ管理系のバグが顕在化しにくいだけ 結局これだよね 本当に丸投げできるなら乗っかるのもいいと思う 性能問題はハードの進化で一部の用途を除けば問題無くなると思うし でも現実は中途半端だから意識して書いたほうがマシだと
あと正確にはGCには含まれないけどメモリコンパクションをやってくれる処理系が多いのも GCを使う利点になるかも
今どき意図的にやらない限りメモリフラグメンテーションで困るような場面があるか? アドレス空間も余裕出てきたし、多少おかしな確保パターンで浪費してもGCほど実メモリを食わないし。 今どき主流のサイズ毎に空きを管理するmallocは優秀だしね。 これがダメならlinuxカーネルとか先に落ちちゃうぞ。
>>469 昔、C/C++を駆使して日本が誇るスパコン京に投入するタスクセットを書き上げたのだが 実行するとどうも性能が出ない。 色々調べた結果、どうやらメモリーが断片化していることが分かった。 そこで多大な投資を行いJavaで書き直したらなんと100倍も性能が上がったのです! これが>>468 さんの経験してきたことなんです。 自前のメモリ管理が超下手くそなだけやろ 修業して出直してこいや
ゲームだとフラグメント問題になること多いよ ゲーム専用機なら特に 最近は特にオープンワールドが当たり前になってるけど あれストリーミングでどんどんメモリ置き換えていくしね
jemallocのようなモダンなmalloc実装使えば良かったのでは。
ゲーム専用機でフラグメンテーションおこすとか開発者としての適性を疑われても不思議ではない。 オブジェクトの寿命管理すらしないのか?
メモリのフラグメンテーションをC/C++でコントロールする方法ってあるの? mallocの実装頼りじゃなく。
mallocの挙動がわかってれば、ある程度は・・・・
細かくメモリ要求するから、下回りで時間がかかる メモリ分断されてもオンメモリでの検索はさほど時間がかからない (空きができても、そこに入らないときに)
>>475 フラグメンテーションって何かわかってないでしょ? 寿命管理だけでは解決できないよ 寿命管理で解決できないとか、フラグメンテーションがどういう現象か分かっているの? 汎用の寿命管理APIみたいなのを使うとか言うのと勘違いでもしている?
>>480 おいおい・・ この場合寿命を管理できないってのはgiven conditionとして考えないと そりゃ寿命があらかじめわかってるなら苦労しないっての 大規模なプログラムでそんな恵まれた状況は例外的だよ 専用ゲーム機上のゲームだよ。 リソースが逼迫したら何を優先するかの戦略も含めてほぼ理想的なgiven conditionだろうに。 ユーザーの行動による不確定性も全てコントロール下にあるだろうに。
まぁテトリスとかならその程度の理解でいいんじゃない?w
>>482 GTAみたいなゲーム考えてみ? あれ全てオブジェクトの寿命を事前に決められると思う? 原理的には不可能じゃないだろうがそんな職人的な作りしてたら開発に10年かかるわw 普通のmallocで足りるならそれでもいいけど。 基本メモリ容量ギリギリまで使うから、最初に描画、ゲーム内部状態、音声、ディスクキャッシュなどでどのくらい使うか決めておく。 終始一貫して静的に決めるのが楽だけど、場合によっては場面ごとに配分を切り替えたりする。 で、例えば広いマップ上を自由に動き回るようなゲームだと、マップを複数のパーツに分割して、詳細モデルから簡易モデルまで用意する。
ゲームプログラムとかならメモリ確保は直接システムコール呼び出して ページ単位でアロケートするのが定石 必要ならmspaceとかインスタンスベースのヒープを自分で作る
使用できるメモリのサイズも空きメモリのサイズも最初から分かってて、ユーザーからの入力も限られてて、 そいつら全部自分で管理できる「恵まれた」環境でしか通用しないアプローチだよなそれ。
レーシングゲームは出てくる車が決まっていてコースも決まっているから。
昨今はレースゲームでも汎用的なゲームエンジン使うことが多いから その場合事前に寿命が決まってる前提の作りにはしていないと思うぞ GDCとかGame Gemとかでも昔からフラグメンテーション対策を含む メモリ管理の手法はいろいろ議論されているから調べてみるとよろし
>>489 ハードリアルタイムなシステムならごく普通 って言うかそうでないと作れない >>486 ああいうFPSのオブジェクトは全部管理されてるし gcなんか使ってないよ やり手のゲーム系の方たちに、逆らうようなことは・・・・
>>494 そんなのどうにでもなるでしょ 汎用のmallocなんかとは事情が違う ゲーム機含む組み込み系は結果が不確定な動的メモリー確保なんかしないのが鉄板(しようとする奴は未熟な馬鹿)だったが PCと合わせて組み込み機器もスペックが潤沢になって富豪的プログラムが一般的になってきたからね 無知ゆえ聞きたいんだが 最近のゲームソフトやら>>497 やらってどういうGC使ってるの? ゲームだって組込みだって今どき動的メモリー確保しないなんて化石みたいな発想が通るわけないだろ かといって普通のGCは問題外 賢いメモリアロケーションをするしかないんだよ >>497 は「こんなすごい講演するぞ」って言う宣伝だけだけど中身はどこにあるの? >>497 MMUが付いているから 物理メモリがフラグメンテーションすることは、ある程度これで防げる しかもハードウェアの機能だから高速だし、勝手にやってくれるから素晴らしい 速度が重要なゲームでは、これは有り難い ソフト的なアプローチでこれ以上の細工は遅くなるだけで効果が薄い 問題は論理アドレスの方 32bit空間だと例え物理メモリが余っていても 論理アドレスがフラグメンテーションを起こして連続したメモリを確保できなくなる 物理アドレスが枯渇するよりもさきに、そちらの方が問題になることが多い 64bitだと、これが防げる 各ゲーム機の事情は知らないが PCで有れば、64bitプロセスは、論理アドレスの空間が256TB(48bit)もある ゲーム機も似たようなものだろう 256TBもの物理メモリを積んだPCやゲーム機は存在していないし 例え論理アドレスが激しくラグメンテーションを起こしても 256TBもの論理アドレス空間を使い切るという事態は考えなくてよい つまり、64bitプロセスなら、論理アドレスの心配はしなくてよい 一方で、物理アドレスのフラグメンテーションはMMUに任せておけばよい これはハードウェアで自動で行われるし、とても高速 その余計にソフトウェア的アプローチで頑張ってみたところで 多少物理メモリのフラグメンテーションは改善されるかもしれないが 徒労というかなんというか、労力に見合わないし しかも遅くなるのでゲームには向いていないし、やらなくてよい 物理アドレスは自分だけが使っているわけではなく、OSを含めたほかのプロセスも使っているので 自分のプロセスが使っている物理メモリだけフラグメンテーションを解消しようと コンパクションするのも何か完璧感が無いし 自分のプロセス内だけで考えても、外部ライブラリやXBoxならDirectXが使用している物理メモリの フラグメンテーションは手が出せないので解消しようがない、やはりやるだけ徒労 自分の管理出来る部分だけ物理メモリのコンパクションをかけても 「これで計算上、必ずあと200MBの物理メモリを使用できる筈」とかといった保証はどこにもない 理由は、外部のライブラリ内での物理メモリの使用状況が分からないし、手が出せないから とにかく徒労であり、MMUに任せておけばよい
ただの物理メモリ不足の話がなんでと思ってしまった swapはじまったら、fpsなゲームはどうなるんでしょうね
論理アドレスが64bitだったらフラグメンテーション対策なんていらんということ?いや自分もそうは思うんだが。 上の方で「専用ゲーム機開発ならフラグメンテーション対策も行うのが常識!」みたいに主張してる人がいて、 それって自作のmalloc相当のアロケータ作るってことだよね?と思ったんだが、 メモリ節約術とごっちゃにしてる人もいてわけが分からなくなってきた。
>>500 すばらしい、正解 まぁ>>488 で答え言ってたわけだけど 某ゲーム機ならコンパクションも実装できるよ >>503 ページ単位という制限がつくし、速いって言ってもシステムコールなので ユーザランドで完結するヒープライブラリに比べると遅い フラグメンテーション対策がいらなくなるわけじゃないよ 用途ごとにセグメント分けて使い回すのが無難じゃないの オブジェクトの数が足りなくなったら透明でいいのよ
結局のところ、物理アドレスのフラグメンテーションはMMUが勝手になんとかしてくれるからあまり問題にならない しかし論理アドレスの方は何にもしてくれないのでフラグメンテーション起こして 連続したアドレスが確保出来なくなると、それで終わり、どうしようもない 32bitプロセスだと4GBしか空間がないから、まれに問題になる 64bitプロセスだと無尽蔵に空間があるから問題になることは現状ありえない
>>510 > 結局のところ、物理アドレスのフラグメンテーションはMMUが勝手になんとかしてくれるからあまり問題にならない MMUってのはアドレス変換するハードウェア 勝手に物理メモリを仮想メモリにマップしたりはしない それをやるのはOS そもそも、ページサイズより粒度が細かいフラグメンテーションにはMMUはなんの効果もないしな。
autorelease()呼んだらコアダンプ糞osがwww
小さな粒度のフラグメンテーションは気にする必要ない 4KBならUTF-16で2000文字ぐらいしかない 32bitビットマップなら32x32ほとのサイズ
>>512 お前のプログラムはメモリを1ページしか使わんのかw? フラグメンテーションで使用率が低いスカスカのページだらけになるのが問題なんだろうが。 >>516 へーお前はヒープを使わないのか 漢だな ネイティブコードが必要な場面で中途半端に GC に頼るのが問題なのかもしれないが、もうネイティブコードが必要な戦場は限られた一部だけになってて、主戦場では GC は大前提の技術なんだから必要ないとか言われましてもですわ。
ページがスカスカになっても大丈夫 1ページ4KBとかだからね、十分小さい 32x32-32bitビットマップより小さい 最近のゲームで使われるような大きなサイズのテクスチャなど でかいサイズを確保する場合はどうせ新しいページが割り当てられるし 小さなサイズを確保する場合は、スカスカになったページから空いているところを探して割り当てられるので 問題ない
androidしか知りませんみたいな事言われてもな
物理アドレスはページサイズで切り売りされるので 元から連続しているアドレスは必要ではなく フラグメンテーションは問題にならない 連続したアドレスが必要になるのは論理アドレスのほうであり 32bitプロセスでは4GBしか空間がないから問題になることがある 64bitプロセスであれば現状問題にならない
実はQtでデーモン作って動かしてるのだが、もう半年以上動き続けてる。 まさかこんなに問題が起きないとは。 案ずるより産むがやすしですぞ皆の衆。
Qtで作ったのは一日ででっち上げる為だったのだが、意外なことに堅牢に動き続けてる。
>>525 デーモンは通常フォアグラウンドじゃないのでUIを持ちませんぜ旦那。 >>526 だからQtでデーモン?(クエスチョン)…なんじゃね? 加えてQtってGC関係あるのか? たしかC++のライブラリーだよね? >>525 Qt 使ってるからと言って QtGui 使ってるとは限らんけどね >>528 Qt 本体は C++ で書かれてるけ ど Java, Ruby, Python, Perl, C# 等からも利用できるよ daemonじゃなくてdemonなんじゃない? デスクトップマスコット的な
俺が作ったのはウェブソケットによってサービスを提供するプログラムだ。 エンジンエックスをリバースプロキシとした。 このプログラムは常時数千の接続から大量のリクエストを受け付ける。 接続してくるクライアントは専用に作られQtで書かれている。 大量のリクエストはそれぞれ複数のデータベース検索を引き起こす。 こう書くと結構負荷が高そうなのだが、さすがC++、ほとんど塵程度の負荷しかなく、 当然のことながらリプライに遅延もない。 そこで案ずるよりも生むが易しというわけ。 Qtは出自からしてGUIのためのライブラリではあるのだが、GUIが無いと使えないというわけでもない。 むしろボリュームからすれば、GUI以外の方がより大きい。 そして、半年動きっぱなしで大丈夫ことからして、実は断片化は気にしなくても 良さそうだ。
ちなみにQt使ってなかったら一日でサービスを書き上げることは不可能だっただろう。 Qtは、その他のGUIライブラリ同様バグが多いのだが、GUIを抜いてみるとどうだろう、 意外なほどに堅牢なのだ。 何しろもう半年動きっぱなし。 俺はこの経験から一つの予測を立てた。 これからのサービスは、C++で書かれるようになる可能性がある。 何しろ圧倒的に速い。 一つのリクエストに対するレスポンスが速いため、平均負荷率が圧倒的に下がるのだ。 この事実に世の中が気づくにはそう時間がかからないはず。 そしてsystemdがこの動きを促進するはず。 ちなみにWindowsで書いてLinuxで動かしてます。
>>530 色々な言語から使えるのか そういう場合Qtが使うメモリーなんかはどういう扱いなんだろうね GC適用外な気がするけど知らないからこれでやめとくわ Windowsで書いてLinuxで動かすことに、systemdは大いに貢献した。 従来のデーモンの作り方では、いろいろ煩雑なことがありすぎ、時間の制限から難しかっただろう。 Qt+systemd、この直観的な選択は大成功であった。
Qtのバグの多くは、複数の環境に対応するため、その差異によって引き起こされているという結論を得た。 systemd万歳!
更にもう一つヒントがある。 複数のクライアントから多様なリクエストがあるとはいえ、一つのプログラムが擁する データ構造などたかが知れているのだ。 クライアントAのリクエストにこたえるため使用された記憶空間は、解放されたのち クライアントBのためにそのまま使われる可能性があるのだ。 そういったわけで断片化は気にする必要が無い。 若者よ、案ずるより産むが易しですぞ。
ねえ訳分かんないんだけど 本人以外で理解してる人要るの?
むしろ、わからないのに何故、一生懸命主張していたのかと。
マークスイープでメモリリークってどうやって起きるんだ? 初心者だから優しく説明してほしい
狭義の意味では起きない もし君が気付かない間にオブジェクトへの参照を保持していたらどんなGCだろうが解放されない それをリークというならリークする
言い換えればダングリングポインタが発生しない それだけ
マーク&スイープでもポインタの型情報を記録してないとリークしまくる 無関係な数値をアドレス参照と勘違いしてマーク→未開放 某言語ではこのために巨大なメモリブロックが開放されない
>>10 C#はGCの掃除処理を任意で呼び出せるだけだろ C++/CLIなら自分でdelete呼べば即座に消え去るが もちろんC++と同じくデストラクタも確実に起動する。 C++/CLIはデストラクタが呼ばれるだけで、managedメモリの解放がGC任せなのは変わらんよ。
匿名通信(Tor、i2p等)ができるファイル共有ソフトBitComet(ビットコメット)みたいな、 BitTorrentがオープンソースで開発されています 言語は何でも大丈夫だそうなので、P2P書きたい!って人居ませんか? Covenantの作者(Lyrise)がそういう人と話したいそうなので、よろしければツイートお願いします https://twitter.com/Lyrise_al ちなみにオイラはCovenantの完成が待ち遠しいプログラミングできないアスペルガーw The Covenant Project 概要 Covenantは、純粋P2Pのファイル共有ソフトです 目的 インターネットにおける権力による抑圧を排除することが最終的な目標です。 そのためにCovenantでは、中央に依存しない、高効率で検索能力の高いファイル共有の機能をユーザーに提供します 特徴 Covenant = Bittorrent + Abstract Network + DHT + (Search = WoT + PoW) 接続は抽象化されているので、I2P, Tor, TCP, Proxy, その他を利用可能です DHTにはKademlia + コネクションプールを使用します UPnPによってポートを解放することができますが、Port0でも利用可能です(接続数は少なくなります) 検索リクエスト、アップロード、ダウンロードなどのすべての通信はDHT的に分散され、特定のサーバーに依存しません w 良スレ発見した。Windowsは32bitで十分だな。32bitでもPAEで4GB超の メモリ認識するし、仮想メモリは4GBのままだが、AWEを使うことにより バンク切り替え的にメモリウインドウを切り替えられる
>>1 みたいなやつは 研究室にヒキって、社会に出たことないんやろ おまえ、本気の糞コードで書かれたペチプ〜とか見たらチビるで あんなんに加えてメモリ管理なんてやらせたら それこそHELLO END OF THE WORLD この世の終わりですわ 指摘してるレスがなかったので言っとくが 循環参照は参照カウント方式+Cycle Collectorでも回収できるから GCは必須じゃないぞ 興味があるならBacon Cycle Collectorで調べてみろ
学生の頃は循環参照できないことに困ってたけど、今となっては何時 循環参照が必要になるかさえ思い出せんな。
>>563 >Cycle Collector いわゆるmark&sweep式とどう違うの? >>568 まずガベージだらけの頭の中を整理すべき >>565 別に 単方向リストでもなるだろJK ていうかリストの要素をshared_ptrにするのは現代でも有効 リストのリンクヘッダ自体の寿命は要素が明示的にdeleteされるかリスト全体が廃棄されるまでなので リンクヘッダも管理したければリスト固有のストレージ丸ごとな単位でshared_ptrにしたら良い、 希ガス △: リストの要素 ○: リストの要素が保持するデータ つか開放タイミングをshared_ptrに任せておk、などという発想のは管理しているうちに含めれないがな…
一般のグラフじゃなくてリスト構造の話だろ? 双方向リストはheadとtailへの参照があるが、単方向リストで循環参照は生じようがないが。
>>572 すまんの>>570 の単方向リストは正確には循環リストもしくは環状リストと呼んだ方が良いかも試練、 だが、循環リストもしくは環状リストも単方向リストの実装方式の一つではある(初期の『プログラミング言語C++』か何かのslist等 のじゃ…! 循環してるかは後付けでオブジェクトをマークすれば判るんだし 扱うデータ構造から可能性の有無は予測できるし循環自体は大した問題じゃないよ あ、これリークするなと思ったら対策すればいいだけ 問題は他人様のブラックボックスなライブラリを使う場合
? 今の議論はプログラマーが何も考えないアホでもGC(言語)使ってれば問題無いのか そうでなければ結局なんらかの管理が必要でちゃんとする事しないとリークするから本質的には管理から開放されないよねって話だと思うが
いまどきの子はブラウザアプリしか作れないから ブラウザ再起動とかページ遷移で解決でしょうな
現在のGCが不完全なだけであって、 メモリは人が管理すべきでないという考え自体は正しいよ。
潤沢なメモリを用意してGCしない戦略 起動時間に限ってGCしなくても問題ない範囲であればGCしない戦略 結局こういうのが勝つ
プロセスを細かく分けて寿命を短くすればそんなの考えなくて済む
本当の意味での軽量プロセスをOSがサポートしてくれたら良いんだけどね メモリプールみたいなもんなんだけど、OSのリソースも紐づいてて メモリプール解放時にOSのリソースもちゃんと解放されるようなもの マルチプロセスは非常に強力で良いんだけど メモリ空間が別になるから色々面倒だしパフォーマンスも出にくい 世の中には呼び出したらしばらく処理が返ってこない時間のかかる関数があるけど とうぜんUIが固まったら困るから別スレッドで実行するわけだけど 処理中にユーザーがキャンセルボタンを押したとき 処理を中断する手段が関数側に用意されてなかったりすると、困る 外からスレッドごと殺しても、リソースリークの問題が出る 真っ先に困るのが同期オブジェクト 同期オブジェクトを握った状態で死なれると、それ以降デッドロックを引き起こす それ以外にも、プログラムの整合性が壊れているかもしれないので、以降正しく動く保証がない だから別プロセスで実行して、キャンセルされたときはプロセスごと殺すしか方法が無い しかし別プロセスにするとメモリ空間が繋がってないので面倒 だからその中間がほしい
いつ無くなってしまうかわからんようなメモリのアクセスが簡単になってもほとんど使いみちないだろ。 安全性重視なら別プロセスにして、必要なデータだけ共有メモリで受け渡してのが妥当なところだろう。
結論から言うと、Windowsにforkが無いのが面倒すぎるってことなんだけどね
>>580 > 処理を中断する手段が関数側に用意されてなかったりする 具体的には? いやそんなもん、中断する手立てが用意されている方が珍しいだろ
元々はスレッドが軽量プロセスって呼ばれていたりしたんだがな(アドレス空間の切り替えが不要だからプロセスより切り替えが軽い) まあそれはおいておいて forkを使うと軽量プロセス?とやらの機能が実現できるらしい理屈がわからない forkしたら別プロセスだぞ? vforkとかなら実行直後は共有しているけど変更を加えた時点で分かれるし まあどちらにしろGCじゃメモリーをはじめとする資源管理からは完全には解放されないって事だ
メモリ空間がつながっていること自体はそれほど考慮してないんよ 単にWindowsはマルチプロセスがしにくい forkあったらちょっとした処理を別プロセスで実行するの、便利じゃん 片づけはプロセスごと殺して終わりだし
GCもハードウェアに支援させれば全部解決するよ リアルタイム処理含めてね
固定領域として静的にグローバル変数化、バッファ化すればいいだろ、 それを汚い言うやつがいるが、 潜在BUGだらけでどうにもできないそれのほうが汚いわ。
例えばChromeとかFirefoxとかが静的にメモリアロケートしてたらどうなるか
そういう発想、嫌いじゃないよ 静的にできるものは、なるべく静的にすべし 俺もそう思う 妙なからくりじみたことにはもう興味が湧かなくなった 最初のころはGCのメカニズムが面白いと感じていたが、もうそういうの、無い いかに静的にシンプルに書くか、こっちのがパズルみたいで面白い すべての事は明確であるべきで、コードはそのようになっているべきだ、と 俺が特に嫌いなのは、何がどの順番に実行されるか、コードを見ただけで よくわからない類のプログラムだ コールバックも基本的に嫌いだ なのでいつ実行されるか分からないマークスイープGCは好きではない 参照カウンタ方式のほうが根本的に安全であり、シンプルであると思う というのも参照カウンタ方式のGCはバグの再現性があるから 唯一の問題は循環参照だが、これも弱い参照を使えば解決する たったそれだけの工夫でマークスイープGCの複雑な仕組みがいらなくなるなら おれはそちらのほうが良いと考える 開放するというただそれだけのことに、あれだけ巨大な仕組みが必要になるのはおかしい
マークスイープ系GCはメモリ管理に関しては完璧かもしれないが それ以外のリソースの面倒は一切見てくれない そういったものはファイナライザで開放すればよいわけだが 要らなくなったらすぐさま開放してほしい時に困るので、例えばC#ではDisposeを用意している しかしながら根本的に本当にDisposeを呼んで良いのかは誰にもわからない部分がある もしかしたら他の誰かが使用中かもしれない、という場面もありうる だから誰も使ってないことをプログラマが保証する格好になる その意味ではfree()と大差ないわけで usingという構文が用意されていて、ある程度自動で呼ばれるというだけである 本当に誰も使ってないことを保証するにはマークスイープを走らせなければわからない しかしマークスイープはコストがかかるので、そんな都度都度気軽に走らせられない その点、参照カウンタ方式は参照カウンタを見るだけで使われているかどうかわかるので 都度都度チェックできるし、要らなくなったらその場で即開放できるので Disposeのような仕組みもいらず、解放処理をデストラクタに一本化できるし スマポを使えばデストラクタ自体、書く必要すらないかもしれない そして有り難いことに、デストラクタはメンバ変数やベースクラスに対しても 芋づる式に自動で呼ばれる これはDisposeには無い機能だ 何故無いのか?答えは、勝手にDisposeして良いのかどうか、コンパイラは判断がつかないからだ 誰か他の人が使っているかもしれないわけで、勝手にDispose出来ない Disposeして良いかどうかはプログラマが保証しなければならないので自動化できないのだ
本当にC#で解放処理をまともに書こうと思うと 自身のクラスのメンバ変数にIDisposableを実装しているものがあるかどうかを調べ もし、実装しているものがあれば、自身もIDisposableにし Disposeメソッドを作り、その中で、先ほど調べたメンバのDisposeを呼び出さなければならない これを手作業でやる C#をやったことのある人なら知っている通り、マイクロソフトの示すIDisposableの実装例自体が 非常に煩雑であるわけだが、ともかく、もれがないように、手作業で頑張る まず、IDisposableかどうか調べ忘れるだろうし、Disposeの呼び出し忘れもありうる mallocしたらfreeしましょうと同レベルのことを強いられる このように面倒なIDisposableであるが IDisposableなオブジェクトをメンバに持つと、自身もIDisposableになるということは IDisposableはどんどん伝染していくわけで、手動でDisposeしまくるコードを書き続ける羽目になる このように、まじめに考えると、破たんした方法であることが分かる 根本の問題はDisposeが自動で呼ばれるコードをコンパイラが生成してくれないこであるが 確実にDisposeして良いかどうかを判断するためにはマークスイープを走らせる必要があるので どうやっても自動化は困難であり、プログラマが開放してよいことを保証するという ある種手作業なusingがせいぜいである 参照カウンタ方式であれば、ほぼノーコストで開放して良いかどうか分かるので これらの問題は一切発生しない 解放処理はデストラクタ一本であるし、芋づる式に自動的に呼ばれるので 手動でコードを書かなければならないということもない ランタイムもシンプルであり、バグった時も再現性が期待できる
これがC++が未だにかたくなにマークスイープ系GCを搭載しない理由である C++を書くプログラマはweak_ptrを適切に使えるものだという前提のもとに マークスイープ系GCにまつわる数々の問題点を排除したのだ マークスイープ系GCで有利なのは唯一循環参照だけであり そこさえ気を付けることができれば それ以外の部分に関しては参照カウンタのほうが優れている C++は別に時代遅れなわけじゃなく、そういう選択をしたというだけ 今になって考えるとその選択は正しかったと思う
メンバーにdisposeしなければならないような設計が良くない。そんなものはメソッド内のローカル変数に止めるべき。 それすらも理解できず(考え付かず)にただ一律なんにでも同じ考え方を押し込むのはただの愚行。 ありもしない、回避可能な杞憂をただ恐れるのは、勉強不足か進歩が止まっているだけ。 だから皮肉を込めて老害と呼ばれる
日本語おかしかった。 メンバーにdisposeしなければならないような物を持たせるのが良くない でした。
>>594 参照カウンタよりも固定バッファを動的に確保ですね判ります >>595 firefoxは解放が遅いのでそれやってるのと実質同じ realplayerとかもそうだったな >>600-601 よくないって言われてそうせざるを得ない場合はいくらでもあるしなぁ 例えば動的に出力先を切り替えられるログクラスみたいな奴をどう書けと言うんだろ? >>597 スマポとデストラクタの必要性は関係ないだろ… deleteの必要がない、とか、デストラクトを考えなくて良いってことだと思うけど。 スタック変数の 0 クリアすら嫌がる C/C++ が GC 搭載とか夢見すぎ
struct test { std::shared_ptr<int> ptr; test(){ ptr = new int; } }; 上のコードはデストラクタを書く必要があるのかないのか スマポを使えばデストラクタを書かなくてよい場合もあり得るということ スマポを使わないのであれば当然デストラクタでdeleteをしなければならないだろう なので、「スマポ」と「デストラクタを書く必要性」は、関係がある ちなみにC#のDisposeはただのメソッドであるので このような芋づる式にメンバ変数のDisposeを呼び出してくれる機能はないし マークスイープなので原理上不可能である 他で使用中でないことをプログラマが保証しないとにはDisposeは呼べないので 自動化できない
>>606 ツボったw 効率至上が利点であり特徴だもんな >>607 それptr.reset()使うんじゃないの? グローバルが嫌われたのは 疑似マルチプロセスでメモリを共有していた時代の汚物だろ 今みたいなOSのメモリ管理ならアプリ単位グローバル常套
C#/C++よりRustだろ 参照カウンタのオーバーヘッドすらない Firefoxに期待
>>612 Write する度に WriteTypeA とかを生成/破棄するってこと? ログとかならその方が望ましいケースもあるかもしれないけど、例えば性能上の問題でストリームは開きっぱなしにしたいとかもあるでしょ >>613 開きっぱなしにしたいスコープは? スコープを一つのメソッドにして、同じようにすればいいじゃない コードが必要なら夜にでも書くよ >>614 スコープを動的に変えたい場合を想定してるんだが 実行中にログファイルを変更できるアプリケーションとか見たことないの? >>615 ログファイルであれば日付で切り替えとかあるね。 そしたらストリーム開きっぱで日付が切り替わったら、閉じて新しいの開き直すとかあるわ。 いつもlog4とか使って主処理と切り離してたから考慮から抜けてたわ。 俺の意見はdb接続とかで一部にしか当てはまらんので、 「基本的には」とか 「リソースを管理する必要があるもの」とか前提がつくね。すまん。 ログファイルはログが確実に記録されるのが使命であって性能は二の次なのだよ よって開きっぱなしは論外 性能で問題が出るなら吐く量を調節すればいいだろう
>>618 アプリケーションエラーとか異常終了した時にバッファされてる内容が書かれないことがあるから 異常終了した時はまさにそのエラーになる直前のログが欲しいのに〜 ってなる w ただログってそういうログばかりじゃないし Apache のアクセスログみたいにいちいち閉じてたら全然間に合わないって現実を知らない >>617 はもう少し経験積むまで黙ってた方がいいと思う >>620 それは開きっぱなしが問題なんじゃなくてflushしてないことが問題なだけで見当違い とこのように、相手を互いに見当違いであると罵り合うのであった しかし、それは正しい 両者とも正しい
スコープの話してるのに flush とか頭わいてるだろ
null安全をアピールしてる人間はObjCerから見ると補助輪付き自転車を渡してきてこれ安全だから絶対に乗れよと言ってくる頭おかしいおじさんにしか見えない Swift移行がこじれるだけだから黙っといて欲しい
浜矩子・著 『アホノミクス完全崩壊に備えよ』 『どアホノミクスへ最後の通告』 『みんなで行こうアホノミクスの向こう側』 抑制のない成長に基づく経済政策は終焉 日本国民はどう対処すればいいのか。 新しい政権は民意を反映し、 食糧、住宅、健康、教育、最後に防衛です。 国民の意志を裏切ることは、 極端な場合、自殺や殺人にまでつながります。 民衆の指導者は 職業的政治家ではない人々から見つかるのです。 世界平和の脅威は、 イスラエル、イラン、アメリカです。 イスラエルの役割は跪いて、 パレスチナに許しを請うことです。 アメリカによる他国の虐待に 反対の声を上げなければなりません。 彼らは今世紀(21世紀)を この帝国が出来上がるアメリカの世紀と呼ぶ。 しかし、そうはならないでしょう。 彼らが世界中に‘民主的’制度を確立したい という衝動(世界を支配する)をコントロール するのは、マイト レーヤの任務です。 非常に間もなく マイト レーヤをテレビで見るでしょう。 彼は「匿名」で働いております。
小規模ならGCのメリットは大きいのかもしれないが、大規模または大量にメモリを食うプログラムにはGCは向いてないのではないか。 あんまり例を知らないが、JAVAで動くマインクラフトのデバッグ画面でメモリ使用量みたら、めまぐるしく増加して一気に減ってるのみてびっくりした。
GC周りに付いて書かれたネットの記事読んできたけど オブジェクトが生成されては次々と死んでいき 生きてるオブジェクトより死んだオブジェクトが多い場合の方が速くなるっぽい >>627 そう考えると長命のオブジェクトが大量にある方が(性能的には)問題だが マインクラフトがそれかは知らない >>606 C++はGC支援のメモリモデルが標準に入った と言ってもコンサバGCライブラリ向けだけどな 参照カウントは循環参照の問題が起こるだけじゃなくて 意外と遅いって聞くけどマジで? ・メモリをOSから直接確保・解放するのは意外と遅い ・マルチスレッドで参照カウントを使うにはアトミックな操作が必要 ・カウントを自動化すると不必要な参照カウントが起こる とかで 対してトレーシングGCの弱点は回収時に止まる時間が長いところか その対策か、V8やOracle JavaにはGCの時間を制限する機能があるみたいだが それってどうなんだ?
ストップ・ザ・ワールドの問題さえなくなればGCが最強ってこと?
>>634 フルGCの危険があるという点で最強になりえない バイオハザード7は28万行のC#コードでできててビルド10秒らしい。 独自VM、独自GCだとか。
>>638 FrameGCはゲームというかRTSに特化したGCだね ・ローカルに発生したオブジェクトは溜め込んでフレームの終わりにまとめて開放する ・グローバルに結びついたオブジェクトにはカウンタGCを適用する ・フレーム毎に循環参照のチェックを少しずつ行う ざっくりこんな感じ? 内部的にC#をC++に変換してるからC#をスクリプト的に使ってるだけで実質C++だな。当然GC・メモリアロケータ周りも身内実装。
>>640 C++のスマートポインタみたいな形で実装できるのかな? 俺は検討してみたけど無理だったw そこまでやって既存のフレームワーク使えるのって疑問が。
「メモリ」+「フラグメンテーション」で検索すると色々と詳しい話が出てくるね。
メモリのフラグメンテーションなど実質的には気にする必要は全くない なぜなら現実のコンピュータにはMMUが付いてるから 物理メモリの連続空間が枯渇することは考えなくてもよい あり得るとしたら32bitプロセスでの論理アドレスの連続空間の枯渇であるが 64bitプロセスにすれば問題ない もともと論理アドレス空間が枯渇するかもしれないほどメモリを使うのなら 64bitプロセスにするのが当たり前なので・・・ というわけでメモリのフラグメンテーションは気にしなくてよい CPUのキャッシュのヒット率を上げるとか、そういうことでなければ
そうなん? ガベコレの回収効率が悪くなって 無駄な使用領域が増えて枯渇しやすくなるんじゃね
>>647 GCのアロケートサイズとページングサイズの区別もついてないアホはスルーでよろしく 程度の問題であって 世のプログラムがフラグメンテーションなど気にせずとも 普通に動いているのを見てわかる通り、問題になってない MMUがあるから
>>646 そういうぬるい環境で済むところもあればそうじゃないところもある ゲームコンソールだと物理メモリサイズに最適化するからな STLとかdefault allocatorで気軽に使ってヒープ汚しまくってると そのうち物理メモリ足りなくなってページアウト 必ず来ると思った、その反論 しかし、稀な事例を持ち出して、どうこう言っても仕方がない
MMU のお陰でふらぐめんてーしょんが起きない環境の方が希だと思うが
フラグメンテーションはアドレス空間や実メモリ量が限定される環境をどううまく使うかの話だから MMUがあって64bit空間なら平気と言われてもな
そそ、複雑なプログラムって書こうと思えばいくらでも複雑化するからな。 で、簡潔で高度と思われる機能を追加していくほど難易度は指数関数的に増大するし。
でも実際スマホアプリ作ってんのにフラグメンテーションを防ぐ為に最初に使用する分全部確保しておいて、その中で割り当てするんだーとかいって、オレオレアロケーター作ろうとする頭の悪いやつがいて困る。 逆にお前の作ったそのアロケーターの中でフラグメンテーションして枯渇するわと。
組み込みなんかでよくあるそういうのは、どっちかというと最初に確保したメモリ以上を 使用しないことを保証するためにやるもんだろう。
アロケータ置き換えるだけでは普通解決しないでしょ >>655 こそが置き換えて何するのか理解できてない気がする むしろ一定時間を保証する(なのでサイズは固定長とかが多い)もんだろ
いくら64bitあっても設計が雑ならメモリ枯渇するでしょ ページング方式でメモリ消費されてんだし
MMUのアドレス変換コストもタダじゃない。 TLBキャッシュ外れたら遅くなる。
ツリー状のメモリ管理するとあっという間にメモリ無くなるな class CTree{ std::vector<CTree>; }; とか
こうするとさらにメモリが消えていくな class CTree{ std::map<std::string,CTree>; };
間違えた。 class CTree{ std::vector<CTree> m_Tree; }; class CTree{ std::map<std::string,CTree>m_Tree; }; で、ツリーのノード一つ毎に上は4kづつ下は8kづつメモリを消費するわけで・・・
一回のメモリ取得で4KBってのが嘘だから意味が無い話だね MMUついてたって、そんなアホな実装は無い 4KBだかの1ページ分の中での細かなメモリ断片化はおおむね無視できる、ということ メモリ断片化で困るのは大きなサイズのメモリを確保しようと思ったとき 連続したアドレスが確保できなくてコケる、ということだからね これに対してMMUは有効ということ メモリが断片化で多少無駄遣いされる分にはスワップしてでも動くから そんでこれは程度問題 大概の場合は問題にならない
https://ja.wikipedia.org/wiki/ 動的メモリ確保 >また、粒度の細かいページングは、ページングテーブル >(物理アドレスと論理アドレスの対応表)が大きくなるため、 >4KB程度の大きなブロック単位でしか割り当てることができない。 ウィキペディア見るとそのアフォな実装がまかり通ってると読めるんだが・・・ アホだなぁ OSレベルのメモリ確保と言語レベルのnew、mallocは別
>>667 ちゃんとmallocやnew時のアドレス確認はしたか??かなりアフォな動作してるぞ? まあ、多少のrealloc程度の処理なら何とかしてくれるけどな。 mallocやnewは 大きなサイズを確保するときと 小さなサイズを確保するときで アルゴリズムが切り替わる
VC++2015での実行結果 auto a = malloc( 10 ); auto b = malloc( 10 ); wchar_t tmp[ 100 ]; ::swprintf_s( tmp, 100, L"a = %x, b = %x \n", a, b ); ::OutputDebugString( tmp ); ---------------------------------------- a = 10a4f0, b = 10a508 残念でしたね
MMUは多少以上の処理をすると簡単にフォールト返すのが困りもの 結局初心者レベルのプログラマしか想定してないんだよな
複雑なことをしていると、それがまるで正しいかのように思う点がアフォ 多少複雑なことをしていてもアフォな挙動をする可能性はあると考えるべき
malloc,newの挙動の説明ってまんまMMUの説明なんだよな だから複雑なアルゴリズムを使われていると思うのはMMUが複雑な挙動をしているから でも、そんなに複雑な挙動してるか?? 単に過去のアプリとの互換性の問題で変な事をしているだけだぞ
たいがいのmalloc,newはMMU次第でいくらでも挙動が変化するからな ちゃんとPC毎に動作確認したか??
ID:S40DCpdn しったかしすぎ mallocの挙動はヒープのアルゴリズム次第
malloc,newの挙動はハードとOSによって変化するという記述は見たことあるけどな
ヒープの管理しないでなんとかなるレベルのものはgc言語使えばいいんでは? このスレの趣旨的にそうでしょ?
自分はメモリ対策プログラムを作って対応したけどな。 メモリサイズを三種類用意して、メモリに対するガードの確実な作りにした。 現在のサイズに使われてるサイズにリミットサイズの三種類のサイズな。 外に出てくるサイズは現在のサイズ、 使われてるサイズはメモリを増やした場合の最大取得サイズで、事実上の取得サイズ、 リミットサイズは取得できるメモリの上限。 で、これらを組み合わせてスーパークラスを作って基本的に対応させてる。
メモリの増減には現在のサイズで対応し、このサイズが必要以上に大きくなると 使われてるサイズを拡張するようにした。リミットサイズは滅多に使わないけれども、 一応対応させた。 メモリに対する読み書きは専用関数を経由して読み書きするようにしたから、 素人が使っても安全なぐらいのプログラムになってる。
あと、動的配列ってのを作って、複数のメモリ取得に対応させた。 メモリにヘッダとフッタを用意して、フッタには複数配列のデータに対応させ、 ヘッダには配列数とメモリサイズを入れてる。フッタには>>682 のデータを持たせた。 ある意味では拡張コンパクションみたいなモノになった。 で、アローケートが一回だけになるようにして、あとはリアロークで対応させた。 おかげでメモリの消費効率は異常なまでに効率よく使えるようになったよ。 あと、動的配列使う場合はいったんメモリをフォーマットするようにしたけどね。
それから、動的配列は入れ子構造にすれば色々と応用がきくようになってるけどな。 で、追記式みたいにデータが動くツリー構造とかが使えるようになってる。
アセンブラできない馬鹿がC++使うことを想定するとGCは成功と言わざるをえない。
メモリを動かして処理すれば出来る事なのにな 出来る事を出来ないというのは間違い
誰へのレスかすらわからないというね 誰も何も「出来ない」という趣旨のレスはしてないと思うが 独り言かね
前日に連続して意味不明な独り言してるやつがいるからそれの続きだろ
malloc()関数の内部はOSからメモリをまとめて取ってくる処理と、 すでに取ってきたメモリを(free()で空きが生じたとき)やりくりする処理の2本立て 前者の処理(システムコールの呼び出し)は比較的高コストなのでmalloc()の度に呼びはしない また後者の処理は、連続したアドレス範囲のメモリを確保できている前提で動く ページングはもっと下のレイヤーで行われるので、 malloc()のコード自体がMMUの有無やOSの違いを関知したりはしない
最近はjavascriptのレイヤーとかまで出来てさらに複雑面倒に
僕の知り合いの知り合いができたパソコン一台でお金持ちになれるやり方 役に立つかもしれません グーグルで検索するといいかも『ネットで稼ぐ方法 モニアレフヌノ』 3682F
GCをルンバで例えたらどうだろう 自動 しかしテーブルの上や 冷蔵庫の中は片付けない 日常生活にさしさわりなく動いてほしい
それに加えてルンバが動けるように床は片付けておかないといけないとか 自動で上手く機能させるために気にしないといけない事が色々ある
もういらないって明示的に書かなきゃならないのなら自前で管理するのと一緒だよな。 アマチュアがサンデープログラムしたり、短時間で終了するアプリならむしろ楽チンだけど、 365日24時間稼働し続けるシステムには致命的な問題になるからなぁ
GCがある言語でも、shallow copy と deep copy のどちらにすべきかの判断が難しくて、結局、間違えてバグの原因になる可能性がかなり残る。 また、C/C++ポインタのミスを危険視する人がいるが、多くの場合はプログラム開発時にテストをすれば間違いが発見できる。 C/C++でのバッファオーバーランを気にする人がいるが、逆にGCがある言語でも、間違って1つ右隣の要素にしてしまったり、処理する個数を1つ間違ったりするミスは有り得て、その場合、厳密な意味でのバッファオーバーランは無くても処理内容自体はバグる。
No GC派なんだけど、WebサーバーをC++とかで実装しても結局力持て余す感はあるよな それだからかなり性能下げてもいいからちょっとでも早く作れるスクリプト言語採用されるってのもありそう
GCのメリットは言語の文法が簡単になること。 GCはスクリプト言語のためにある。
(destructor)() dispose() destroy() close() free() delete