パスワードを忘れた? アカウント作成
この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。

もうやらなくていい昔のコーディングテクニックあれこれ」記事へのコメント

  • malloc/freeの処理コストってどれくらいかかるんだろう。メモリがバカ高かった時代はmalloc/freeで使用量を厳密に、というのはわかるんだが、ンGB当たり前の昨今、malloc/freeの処理コストの方が高くなったりしないのかな?と。「だいたい、こんくらいとっといてぇー」というようなプログラミングスタイルは無いのだろうか、と思う。

    ・・・malloc/free叩いとらんな、最近。

    --
    -- gonta --
    "May Macintosh be with you"
    • Re: (スコア:2, 興味深い)

      >malloc/freeの処理コストの方が高くなったりしないのかな?
      >と。「だいたい、こんくらいとっといてぇー」というようなプログラミングスタイルは無いのだろうか、と思う。

      チマチマ何回かに分けて取るより一回にまとめて取った方が相対的に安くなる
      ので、「だいたい、このくらい」でまとめて取ってから、それをアプリ内部で
      チマチマ切り刻んで使うというテクニックは昔からあったと思います。

      そしてJVMなんかだと、それを自動でやってくれるので、Javaな人にとっては
      これも「もうやらなくていい昔のコーディングテクニック」の一つですね。

      それから、OSが仮想記憶をサポートして以降は、mallocは実メモリを確保する
      わけではなくOSの管理テーブルに予約するだけなので、ちょっとくらい大きい
      領域を予約しても影響はすごく小さくなってるはずです。

      • by Anonymous Coward
        特に、常駐プログラム(そう、デーモンとかサービスとか)だと、わずかなメモリリークでも、起動して一年後にシステム停止なんてことになって、深夜呼び出し&スッゴイ怒られる、ので、未だに、メモリ管理の仕組み自体は、できるだけ自前で作りたいという人は多いかと。
        そうか、Javaだと(よほど変なことをしない限り)メモリリーク心配しなくていいのか(本当?)でも起動時に1GByte以上のヒープサイズが必要ですとかいわれると、いくらメモリ安くなったとっていってもすこしひくなぁ。
        • >そうか、Javaだと(よほど変なことをしない限り)メモリリーク心配しなくていいのか(本当?)

          いえいえ、お馬鹿なコードを書くとリークしていきますよ。
          使わなくなったオブジェクトに対する参照をつかんだままにしてれば
          いくらでもメモリ使用量は増えていきますから。

          スコープを外れた変数のつかんでるオブジェクトの回収とかは勝手にやってくれますが
          変数参照が生き残っていれば回収できないのです。
          プログラムグローバルなキャッシュを何も考えずに書かせると、そんなコードができるんじゃないですかね。
          ただ、まぁ、そうはいってもCに比べれば格段に問題のあるコードは書きにくくなっているでしょうね。

          • by firewheel (31280) on 2009年05月04日 17時23分 (#1559100)

            >>そうか、Javaだと(よほど変なことをしない限り)メモリリーク心配しなくていいのか(本当?)
            >いえいえ、お馬鹿なコードを書くとリークしていきますよ。

            「メモリリーク」という単語を、
            「ポインタ(或いは参照)を全て手放したにもかかわらず、領域の解放(free)を
             忘れたために、メモリを少しずつ食い尽くしていく現象」
            と定義するなら、Javaだと「メモリリーク」の心配はほぼありません。
            #まさに「よほど変なことをしない限り」、且つ「VMやフレームワークにバグがない限り」。
            #C言語で長期間動作するアプリを作るのが難しいのは、このような「狭義の
            #メモリリーク」の検出とデバッグが難しいからで、Javaではそれが発生しない
            #ことがサーバー向けアプリに適している理由でもあります。

            少なくとも昔は「メモリリーク」というのはそういう意味で使われているものだと
            思っていましたが、最近では参照を掴んだまま離さない
            「到達可能なオブジェクト」=「(GC的に)生きているオブジェクト」
            が生き残っているのも「メモリリーク」だと呼ぶ人はいます。
            そういう「広義のメモリリーク」ならばJavaでも起こりえます。
            #これはGCの基本的な特性なので、おそらく他のGCを持つ言語でも同じになる。

            でもこれは言うまでもなくC言語でも他の言語でも起こることですね。そういう
            コードしか書けない人は、いずれにせよC言語で長期間安定動作するようなコードは
            書けないので、Javaにおける広義のメモリリークの心配をするには十年早いかと。

            親コメント
            • by CowardDuck (25674) on 2009年05月04日 17時58分 (#1559122)
              長期運用するとメモリの消費量が増えてゆくように見えるなら
              言葉の定義がどうであろうと起きている現象がなんであろうと
              問題ですね。

              このメモリリークの広義/狭義(あるいはメモリリーク/メモリリテンション)って
              のは良く聞く話なのだけど運用者にとっては区別する意味が全くない。

              この話を聞いて私が思い出す言葉は「五十歩百歩」です。
              親コメント
              • by munesato (619) on 2009年05月04日 18時05分 (#1559127)

                御指摘の通り、長期運用を考慮していないという意味で問題だと思います。

                ただ、Javaに限定した場合、最大メモリ使用量が予め設定されているので、
                (その範囲を超えないという意味で)OS側への影響は与えにくいですね。
                JVMで確保したメモリ内で段々と空き領域が減っていく・・・という話になります。

                # 個人的にはOS上のメモリ使用量しか見てない運用者というのがいて、
                # JVM内のメモリ使用量を把握していない例が多いのが頭痛の種。(T-T

                親コメント
              • by firewheel (31280) on 2009年05月04日 18時11分 (#1559130)

                >運用者にとっては区別する意味が全くない。
                >この話を聞いて私が思い出す言葉は「五十歩百歩」です。
                プログラミングが分かってない人の意見かな。

                運用者にとっては違わないかもしれないけど、開発者にとっては全然違いますよ。

                狭義のメモリリークはデバッグが凄く難しい。
                それに比べ広義のメモリリークは対応が遥かに容易。

                結果として、開発に同じだけのリソースを割り振った場合に、
                Cで作った場合は開発期間が長期化しメモリリークが多く不安定で、
                Javaで作った場合は短い開発期間でもメモリリークが少なく安定する、
                という違いとなって現れることが多い。

                もちろん無限の開発コストと無限の開発期間がつぎ込める場合はこの限りではありません。

                親コメント
              • by Anonymous Coward

                結果を区別する必要は無いけど、
                原因を区別する必要は有るね。

                区別する気が無い人なら運用者にもならないで欲しい。
                なぜならその人は、バグったときにその区別ができるような情報をデバッグ者に渡す「気」が無いわけでしょ?

                そういうところで情報断絶をおこしてデバッグが立ち往生すること、実際凄く多いんだよorz
                つまりそういう場合にバグがいつまでたっても直らないのはハッキリいってそいつのせい。

                全く気にする必要が無い人はそれはエンドユーザというんだよ。運用者じゃない。

                運用者は開発者とともに
                原因と結果の界面に居る人だ(でないと困る)。両方に目配りをしてもらいたい。

              • Re: (スコア:0, フレームのもと)

                >>運用者にとっては区別する意味が全くない。
                >>この話を聞いて私が思い出す言葉は「五十歩百歩」です。
                >プログラミングが分かってない人の意見かな。

                >運用者にとっては違わないかもしれないけど、開発者にとっては全然違いますよ。

                >狭義のメモリリークはデバッグが凄く難しい。
                >それに比べ広義のメモリリークは対応が遥かに容易。

                狭義/広義と使い分けているが、ただ単にスキル不足な気がする。
                昔ならいざ知らず、統合開発環境が主流な現在においてはどちらも容易。
                (ブレークポイント張りまくれるでしょ。スタックの中身ですら見えるでしょ。)
                プログラミングが分かってない人の意見かな。<

              • by firewheel (31280) on 2009年05月04日 22時05分 (#1559236)

                >昔ならいざ知らず、統合開発環境が主流な現在においてはどちらも容易。
                >(ブレークポイント張りまくれるでしょ。スタックの中身ですら見えるでしょ。)

                ブレークポイントはどこで何が発生するか分かってないと張っても無駄です。

                (狭義の)メモリリークの難しい点は、それを発生させる条件を特定することや、
                或いはそもそもメモリリークの有無を知ることそのものなんですよ。どういう
                条件の時にメモリリークが発生するのかまで特定できていれば、その部分のバグに
                ついては8割方片付いたも同じです。

                ブレークポイントはその残りの2割のさらに一部を楽にできる程度の効果しかありません。
                #そもそも統合開発環境がある前からデバッガなんてありましたよ。
                #ブレークポイントをはったりもやってた。でも(狭義の)メモリリークは
                #最も面倒なバグの一つとして有名だったのです。

                >出来ない君集団にやらせるなら、何使わせても一緒じゃね!?
                この部分についてだけは同意。

                親コメント
            • by Anonymous Coward

              > でもこれは言うまでもなくC言語でも他の言語でも起こることですね。そういう
              > コードしか書けない人は、いずれにせよC言語で長期間安定動作するようなコードは
              > 書けないので、Javaにおける広義のメモリリークの心配をするには十年早いかと。
              おかしくね?
              Javaにおける広義のメモリリークを起こすようなコードを書く人は
              その心配をしたほうがいいんでは・・・?

            • by Anonymous Coward

              >#まさに「よほど変なことをしない限り」、且つ「VMやフレームワークにバグがない限り」。
              >#C言語で長期間動作するアプリを作るのが難しいのは、このような「狭義の
              >#メモリリーク」の検出とデバッグが難しいからで、Javaではそれが発生しない
              >#ことがサーバー向けアプリに適している理由でもあります。

              これ、素直に初耳なんですけど。。
              サーバ向けアプリで知っているとすれば、銀行勘定系(COBOL)のフロントUI位なんですが、
              そんなに、サーバー向けアプリ+Javaって多い!?
              また、開発言語の選択基準がメモリの確保/解放が決め手になるなんて、どんだけ幼稚なんだと

              • by komakisakio (33768) on 2009年05月04日 20時28分 (#1559192)
                > そんなに、サーバー向けアプリ+Javaって多い!?

                ・言語としてのシェアがトップクラス
                ・Javaをクライアントサイドで使うことは少ない(携帯Javaはそこそこ多いけど)

                ということを考えると、かなり多いのでは?

                > 動的メモリを確保できる言語は、メモリリークの問題を常に持っている。

                一見、動的メモリ確保をしていないように見えても、メモリリークすることがあります。
                g++2.9.5(だったかな)で例外をcatchするとスタックが本来の位置より数bytesせり上がるというバグがあって、長期間動かすと徐々にプロセスのメモリ使用量が増えていくという現象に出くわしました。あれは怖かった。
                親コメント
              • by firewheel (31280) on 2009年05月04日 22時18分 (#1559240)

                >サーバ向けアプリで知っているとすれば、銀行勘定系(COBOL)のフロントUI位なんですが、
                >そんなに、サーバー向けアプリ+Javaって多い!?

                むしろ日本の銀行だけが未だにCOBOLとかを使っているガラパゴスで、
                外資系金融機関などはのきなみJavaへのリプレースが済んでるそうですよ。

                Googleも元は90年代に作られたのでC言語だったけど、とっくにJavaを使う
                方向に変更されてるし。

                >また、開発言語の選択基準がメモリの確保/解放が決め手になるなんて、どんだけ幼稚なんだと。。
                これは「大間違い」です。

                Javaがサーバーサイドで利用される理由は、マルチスレッドとの親和性、
                豊富なライブラリ、パフォーマンス、高い生産性など、それらの総合評価
                によるものです。決してGCが「決めて」になったわけではありません。

                しかし、もしそれらのメリットがあったとしても、もしメモリリークを引き起こし
                やすい言語であれば、これほどまでに利用されることはなかったかもしれません。
                それくらいメモリリークはサーバーサイドでは厄介な問題と言えるのです。

                >メモリの解放忘れをメモリリークと呼ぶのも問題無いと思うが?
                いえ、「解放を忘れてる」のだけではなく「動いている」のです。

                #車で言えば、「赤信号で停車している」のではなく、
                #「アクセルを踏んだままにしている」くらいの差がある。
                #アクセルを踏んだままなので、エンジンを止めるわけにはいかないのです。

                親コメント
              • これ、素直に初耳なんですけど。。
                サーバ向けアプリで知っているとすれば、銀行勘定系(COBOL)のフロントUI位なんですが、
                そんなに、サーバー向けアプリ+Javaって多い!?

                一時期、DBを叩くWEBアプリをTomcatのようなJavaフレームワークで構築するのが流行りましたよ。
                今時はマシンパワーが上がったのでPerlやPHPやRubyを使うようになりましたけど。

                また、開発言語の選択基準がメモリの確保/解放が決め手になるなんて、どんだけ幼稚なんだと。。
                <確かにそんな話する、トンでも外注(害虫!?)もいることにはいるけどなぁ。。

                既出っぽいですけどメモリアロケーションの実体が言語インタプリタにあると言うのはメンテナンスの面からはやりやすいのですが。コンパイラでネイティブコードにした物を動かした場合のこの手のバグ潰しのややこしさを考えると…

                まぁ、純粋にCだけで書いて必要なメモリは必ずmalloc噛ます。構造体すら一度mallocして割り当ててしまう。とかそういう非常に神経質にやる場合は例外として、下手なC++コンパイラとかみたくオブジェクトバンバン作って後で変な残りカスが出てしまうというのはどこにバグの責任所在があるか見極めるのが非常に難しい。
                特に多くのプロセスが立ち上がったり消えたりを繰り返す場合には見えないメモリリークの蓄積で仮想記憶領域を食いつぶし、マシン飛ばしたり速度落としたりとか普通にありますよ。
                # MPU自体が完璧に近いガベージコレクション機能を持てばC++も信頼出来るようになるのですが、
                # 今はOSカーネルのGC機能とコンパイラの正確さ頼みだからな…

                動的メモリを確保できる言語は、メモリリークの問題を常に持っている。
                この位の事を理解していないと、言語の種類なんか関係なくロクなコードなんか書けないと思けど。

                このあたりは[全体|詳細]設計とか誰にどこのコーディング振るかというプロジェクトマネージメントとかの問題でコーディングに入る前に理詰めで潰せていないとどうしょうもないですよ。それでもコーディングに入ったら最初はリークバリバリになりがちで、それが書き方の問題か組み合わせの問題か容易に見分けられる準備していないと。
                一つ一つのルーチンがメモリリーク潰せていても、組み合わせた場合にどうかというのはまた違う。
                設計段階でメモリリーク誘発しにくいように見極めが出来ていないとダメなのでは。

                親コメント
              • by Anonymous Coward
                Cでのメモリリークというと、領域の開放し忘れじゃなくてフラグメンテーションのことだと思っていたヨ
              • by Anonymous Coward
                その認識は明らかに間違っている。
                フラグメンテーションが起きるのは結果です。
                たとえば、256KBの領域があるとき、100KB、1KBと確保して、100KBを解放すると、100KB+155KBの2つになります。後から200KBを確保できません。
                その1KBがリークしていたら、もう200KBを確保できることはありませんが、1KBが解放されれば200KBを確保できることがあるかもしれません。
                しかし、実際の問題としては必要な時に必要なメモリを確保できなければ、実行できません。

                Win32アプリなんか、ちょっとスレッドを動かすと、スレッド用スタックでメモリが分断されて、256MBを超えるメモリは1つくらいしか確保できません。実際使い物にならないけど、これをメモリリークとは言わないし、言語Cとは限らない。
              • by Anonymous Coward
                > たとえば、256KBの領域があるとき、(以下略)

                しかしJavaなどGCのある言語では、かような場合でも自動的にコンパクションを行いますから、Cよりも本質的な部分で楽でしょう。
                Cなどでは適切な順序でメモリの解放を行わないとフラグメンテーションを起こしてしてしまいますし、これが大変やっかいなバグとなることは周知のとおりです。
                (フラグメンテーションがメモリリークを引き起こす、とでも言いましょうか)

                メモリの解放忘れというのはごく初歩的なミスですから、メモリリークなどという大層な呼び名を頂いているとは思わなかったということです。
                ただのメモリの解放忘れが引き起こす現象もメモリリークと呼ぶということであれば、認識を改めます。
              • by Anonymous Coward
                > スレッド用スタックでメモリが分断されて

                メモリをたくさん使いたいなら、DLLのロードアドレスやスタックの置かれる場所やサイズを、自分で指定しなきゃ。
              • 少なくとも Visual C++ では、メモリーを確保して解放しないことを「メモリーリーク [microsoft.com]」と呼んでいます。日本語版のドキュメントでは「メモリ リークとは、割り当て済みのメモリを正しく解放できない状態を指します」と、わかったようなわからないような説明になっているので、英語版 [microsoft.com]から引用します。

                One of the most subtle and hard-to-detect bugs is the memory leak―the failure to properly deallocate memory that was previously allocated.

                (訳: 最も微妙で最も見つけにくいバグの一つがメモリーリーク、すなわち確保したメモリーを正しく解放しないことである。)

                親コメント
              • by Anonymous Coward
                failureとあるので、(プログラマがメモリを解放しようとしたにもかかわらず)失敗した、というニュアンスでしょう。
              • failureとあるので、(プログラマがメモリを解放しようとしたにもかかわらず)失敗した、というニュアンスでしょう。

                failure は「何かをしようとして失敗すること」とは限りません ( [alc.co.jp])。とはいうものの、おっしゃる通り、「failure to deallocate」という英語の解釈としては「プログラマーはメモリーを解放しようとしているにもかかわらず (何らかの理由で) 解放に失敗すること」というのもありえますね。メモリーリークというのはそういう意味ではないと思っていますが、証拠を挙げるのは僕には難しいです。

                親コメント
              • by Anonymous Coward
                > 特に多くのプロセスが立ち上がったり消えたりを繰り返す場合には見えないメモリリークの蓄積で仮想記憶領域を食いつぶし、マシン飛ばしたり速度落としたりとか普通にありますよ。

                具体的に、どんなOSで?

                WindowsやLinuxでは、mallocやnewしたものをfree、deleteし漏らしてメモリリークしても、プロセスが終了したときには、当該のプロセスがプライベートに確保したメモリはすべて開放されますよ。
              • by Anonymous Coward
                DLLの手動ローディングやらスレッドのスタックサイズやらは指定できますが、それでは解決しませんでしたね。

                もし知っていたら、後学のために教えてください。
                _beginthreadex()でもCreateThread()でもスタックの開始アドレスは指定できませんが、どのようにすれば、スタックのアドレスを指定できるのでしょうか?
                また、MFCなどがIEコンポーネントを使ったり、ウインドウを開いたりして、内部で使ったメモリの位置を指定したり、解放する方法も知っていたら、教えてほしいです。

                64bit OSが一般的になれば、"昔のコーディングテクニック"の仲間入りですが、まだ使えるので、可能ならば知りたいです。
              • by Anonymous Coward
                > Win32アプリなんか、ちょっとスレッドを動かすと、スレッド用スタックでメモリが分断されて、256MBを超えるメモリは1つくらいしか確保できません。

                連続したアドレス空間が必要なら、早々にVirtualAllocで予約すべし。
            • by Anonymous Coward

              え?Javaでもマルチスレッド処理なんかでは一見GCにより開放されると思われる箇所でもメモリーリークを起こしますよ。
              中規模以上のプロジェクトで2~3件の頻度ですが...

            • by Anonymous Coward

              もしかしてConservative GCのことを語っている?

アレゲはアレゲ以上のなにものでもなさげ -- アレゲ研究家

処理中...