2010-12-02 2 views
6

mallocが動的にmemを割り当てるため、理解できることから、そのmemを解放して再度使用できるようにする必要があります。あなたはmalloc関数(つまり、あなたはそれを解放することになっているか) すべてのmalloc呼び出しを解放する必要があります

  • を使用して作成された、char *を返す場合は、それが あるようにポインタを残して、アプリケーションを終了すると、それが を解放されます何が起こる

    1. (私はこれについて明確な答えを見つけることはできません。
  • +0

    あなたは何をすべきかについて決定的な答えは見つけられませんが、標準で何をしなければならないかについての決定的な答え(それは気にしません)と、すべての現実のオペレーティングシステムDOS - どちらも気にしない)。気にしている組み込みシステムは、おそらく 'exit()'の概念を持っていないかもしれませんが、私が間違っていることを証明するために誰かが立ち上がると確信しています。 :-) –

    答えて

    6
    1. 発信者はそれを解放する必要があります(または解放するようにしてください)。つまり、リソースを作成して返す関数は、解放する方法を正確に文書化する必要があります。

    2. 「プロセス」の定義の一部として、プログラムが終了するとほとんどのOSがメモリを解放します。 Cの標準は何が起こるか気にせず、プログラムの範囲外です。すべてのOSに完全なプロセス抽象化があるわけではありませんが、デスクトップスタイルのOSは確かにそうです。

    あり、その前にそれを解放する主な理由:

    • できるだけ早くあなた空きメモリ、プロセスの終了前に、多くの場合、長い時間の場合は、あなたのプログラムは、少ないメモリの合計を使用しています。
    • これを解放せずに、後でプログラムを別のプログラム内のルーチンに変更したい場合は、何度か呼び出されている可能性があります。
    • プログラムの終了時にまだ割り当てられているメモリについて警告することにより、メモリリークを特定するのに役立つデバッグツールがあります。故意に流出するジャンクがたくさんある場合、これらはあまり役に立ちません。
    • これを解放せずに問題が発生した場合は、後で元に戻すことがより難しくなります。
    • メモリを解放して(長時間実行しているプログラムではメモリを大量に使用しないようにする)必要がある場合が多くあります。そのため、デフォルトの戦略ではすべてをきれいにする必要があります。

    解放しない漠然ともっともらしい理由は、次のとおりです。

    • 少ないコード。
    • プログラムの終了直前に個別にブロックする必要がある場合は、OSにプロセス全体をドロップさせるほうがずっと速いかもしれません。
    • 必要に応じて作成され、グローバルに格納されたものは、使用場所を正確に知らないと安全にクリーンアップするのが非常に難しいかもしれません。あなたが進むにつれて読み込まれたキャッシュのようなものを考えてみましょう。それは、どれだけのメモリを占有するかを制限するMRUルールを持つかもしれないので、無制限のリークではありません。 OK、これは別の悪いこと(未処理のメモリ)を引き起こす1つの悪いこと(無制限のグローバル)ですが、既存のコードに未処理のブロックがある理由を知る価値があります。それら。

    フリーズの理由は、ほとんど常にその理由を上回ります。

    +0

    私はこの答えを他のものよりも受け入れた理由は、ポインタを返す代替のアプローチが提案されたからです。他の回答に間違いはありません – RC1140

    +0

    私は、メモリを解放せずに、悪用されたままにしておくと、特にメモリを増やしてから使用することをお勧めします。 https://en.wikipedia.org/wiki/Buffer_overflow#Heap-based_exploitation – Caperneoignis

    3

    はい。あなたがmallocなら、あなたは自由にする必要があります。あなたは無料でいない場合、あなたのプログラムが実行されている間、メモリリークを保証しています。

    無料です。

    常に。

    期間。

    +1

    +1いつも良い習慣です。例外はありません。プログラムが終了すると、スキップすることができます。通常は終了しないサーバープロセスはどうですか?漏れは大丈夫だと思う習慣に入らないでください。 – EvilTeach

    2

    はい、malloc()へのすべての呼び出しは、free()への呼び出しと一致する必要があります。

    はあなたの特定の質問に答えるために:

    1. あなたが明示的に返されるポインタはfree()
    2. は、OSがプロセスに割り当てられたすべてのメモリを解放しますD」であることを持っているかどうかをユーザーに伝えるあなたのAPIを文書化する必要があります。
    +1

    @ソフトウェアモンキー、それらはGNU番号ではなく、Unixのマニュアルセクションです。http://en.wikipedia.org/wiki/Man_pageを参照してください。 –

    +0

    とにかく「グヌー数」とは何ですか? –

    +0

    彼らは何でも、この文脈では属しません。しかし、彼らが何らかの利益をもたらすと思うなら、それらを戻すことを自由にしてください。 –

    0

    1)あなたは、通常のメモリを解放したいのと同じ方法、すなわち

    p = func(); 
    //... 
    free(p); 
    

    トリックはあなたが常にそれを行うことを確認することである...

    2)一般的に言って、はい。しかし、あなたは良い実践としてあなたが使用しているメモリを解放する必要があります。メモリを解放する場所を見つけ出す時間を費やしているだけで、怠け者になっています。

    6
    1. あなたはmallocによって作成されたメモリへのポインタを持っている場合は、freeそのポインタを使用して、そのメモリをINGのは、正しいことを行います。はい、いくつかの魔法が関わっています。これはコンパイラによって処理されます。

    2. はい、メモリ解放を無視してアプリケーションを終了すると、OSはメモリを解放します。しかし、それを未処理のままにするのは悪い習慣とみなされます。 OSは(特に組み込み設定で)正しいことをしないかもしれませんし、適時にそれをしないかもしれません。また、プログラムを継続的に実行していると、メモリが大量に消費され、最終的にメモリが消費され、メモリ不足とクラッシュする可能性があります。

    0

    1. ...のは、一度にこれらの一点を見てみましょうあなたはmallocで作成された知っているchar *を返す場合は、[はい、それを解放する責任があります。 free(myCharPtr)でそれを行うことができます。

    2. OSはメモリを永久に失うことはなく、永遠に失われることはありませんが、アプリケーションが終了した直後に再利用される保証はありません。それはオペレーティングシステムに依存します。

    2

    自分で関数を記述する場合は、それを避けてください。

    • 代わりに、呼び出し元にバッファを渡し、呼び出し元にバッファのサイズを指定させ、そのバッファにデータをコピーさせます。そうすれば、同じヒープ(他のプログラミング言語、異なるCランタイム...)を使用しない他のモジュールの関数を使用することができます
    • このようなインタフェースを使用できない理由があれば、呼び出し元が返されたポインタを処理した後にそのポインタを解放しなければならないことを示すドキュメント。

    ライブラリ関数を使用している場合:ドキュメントを参照してください。

    • 文書に自由にする必要があると記載されている場合は、そうしてください。
    • ドキュメントに、必要でないことが記載されている場合、モジュールのリソースを解放するために呼び出される必要があるグローバルクリーンアップ関数があります。

    2番目の質問については、終了する前に解放することをおすすめします。技術的には傷つきませんが、大きなプロジェクトでコードを再利用したい場合は、最初に正しいクリーンアップを書いたことに感謝します。

    +0

    あまりにも不便でない場合は、最初の箇条書きの例を挙げることができますか?すなわち、「発信者にバッファを渡させる」 – Abdul

    +1

    例は、[snprintf](http://www.cplusplus.com/reference/cstdio/snprintf/)関数です。最初のパラメータは、関数によって満たされるバッファへのポインタであり、2番目の引数は、このバッファの長さを指定します。 – Timbo

    0

    すべてのmallocを解放しなければならないとは言いませんが、プログラムがどれだけ長く実行されても、割り当てられた割り当て数(および合計サイズ)解放される。この数は静的な定数である必要はありませんが、何か他の点で指定可能でなければなりません(例:このプログラムはウィジェットを処理します;最大のウィジェットの各クイズに1つの64バイトの構造体を割り当てます)。最大のウィジェットのサイズを事前に知ることはできませんが、例えばウィジェットを処理するのに必要な一時記憶域がそのサイズの2乗に比例することを知っているなら、最大のウィジェットが十分に小さく、メモリの総量がかなり少なくなることは間違いないだろう。

    0

    C標準には、単一のプログラムの実行以外のシステム環境という概念がないため、「プログラムが終了した後」に何が起こるかを指定することはできません。同時に、mallocで得られたメモリは、でコールする前に解放する必要がありますか、またはからコールするか、またはmainから戻る必要があります。手動でメモリを解放せずに終了するというのはかなり明らかですすべてのファイルを閉じずにexitを呼び出すと、自動的に閉じられます(フラッシングを含む)。あなたの特定のプログラムに多くを依存するかどうか、あなたべきべきではないコールfree、用として今

    、。

    • 任意のライブラリコードは、それができるだけ早く内部使用のために純粋に得たことを任意のメモリをfree必要があります。
    • 呼び出しプログラムに割り当てられたオブジェクトを返すライブラリは、常にそれらのオブジェクトを解放する対応する呼び出しを提供する必要があります。
    • グローバル初期化の一部として割り当てを実行するライブラリ(注意:これは非常に悪い設計ですが、時には避けられない)は、アプリケーションが初期化を取り消し、割り当てられたすべてを解放する方法を提供する必要があります。これは、ライブラリが動的にロードされる可能性がある場合(動的にロードされる別のライブラリの依存関係を満たした結果としても)特に重要です。

    これまでのところ、図書館のコードについてしか話しませんでした。この時点で残されているのは、アプリケーション自体によって、またはライブラリによってアプリケーションに代わって割り当てられることだけです。私の見解では、私はそれが非正義であることを認めます、そのようなオブジェクトを解放することは、不必要ではなく有害であるということです。私がこれを言う主な理由は、ほとんどの長期間使用されているアプリケーションでは、かなりの量の割り当てられたメモリが蓄積されていることです(ワープロやブラウザーの履歴の取り消しバッファーを考える)。適度にロードされたシステムでは、このデータの多くは、アプリケーションが終了するまでにディスクにスワップされています。あなたはそれを解放したい場合は、

    • は、ハードドライブの物理的な構成部品に無用な摩耗を入れ、スワップアウトされたメモリアドレスを解放するためにすべてのポインタを追跡するすべての上を歩いて終了するつもりだ
    • ユーザーは、それらが遅く

    あなたが解放する必要がありばかばかしいの名の下に、こののすべて」を実行すること、他のまだ使用中のアプリケーションのデータがスワップアウトを取得させる

  • を終了するようにアプリケーションを待つ作りますあなたが割り当てたすべてのものです。

    短命のアプリケーションではそれほど大したことではありませんが、すべてのメモリを解放する必要がない場合は、単一の線形タスクと終了を実行する短命アプリケーションの実装を単純化することができます割り当てます。ほとんどのUNIXコマンドラインユーティリティを考えてみてください。終了する前に、すべてのコンパイル済み正規表現を解放するために、sedのためのループを書くことにはどんな使い方がありますか?プログラマーの時間をより生産的なものに費やすことはできませんでしたか?

  • 関連する問題