mallocとスコープ

私はmallocの周りを頭の中で包み込むために、特に自由でなければならないときには苦労しています。私はgccで奇妙なエラーが発生しています:

... free():無効な次のサイズ(高速):...

私はcharポインタを解放しようとします。たとえば、入力ファイルから読み込むと、次の行を実行すると特定の行でクラッシュします。

FILE *f = fopen(file,"r");
char x[256];
while(1) {
    if(fgets(x,sizeof x,f)==NULL) break;
    char *tmp = some_function_return_char_pointer(x); //OR malloc(nbytes);
   //do some stuff
    free(tmp);//this is where I get the error, but only sometimes
}

xがNULLであるなどの明白なことを確認しましたが、そうではありません。それはちょうどランダムな線でクラッシュします。

しかし、私の本当の質問は、 - 無料()をいつ使う必要があるのですか?あるいは、おそらくより正確に、いつ私は無料で使うべきではありませんか? mallocが関数内にあり、malloc()を使ったvarを返すとどうなりますか? forループまたはwhileループはどうですか?構造体の配列に対するmallocingは、文字列/ charポインタと同じ規則を持っていますか?

プログラムのクラッシュ時にgccに入っているエラーから、私はmallocとfreeを理解していないだけです。私はGoogleと質の高い時間を過ごしましたが、まだ私はレンガの壁に当たっています。あなたが見つけた良い資源はありますか?私が見ているすべては、mallocを使うたびに無料で使う必要があると言います。しかし、私はそれを試み、私のプログラムはクラッシュします。変数のスコープに基づいて異なるかもしれません。変数が内部で宣言されているとき、Cはループの終わりにメモリを解放しますか?関数の終わりに?

そう:

for(i=0;i<100;i++) char *x=malloc(n);//no need to use free(x)?

しかし:

char *x;
for(i=0;i<100;i++) {
    x=malloc(n);
    free(x); //must do this, since scope of x greater than loop?
}

そうですか?

うまくいけば私は意味を作っている...

1
何かあなたはmalloc()、あなたはもうそれを使用する必要がなくなったとき(1回)無料です。
追加された 著者 Mitch Wheat,

7 答え

malloc() is C's dynamic allocator. You have to understand the difference between automatic (scoped) and dynamic (manual) variables.

Automatic variables live for the duration of their scope. They're the ones you declare without any decoration: int x;

Most variables in a C program should be automatic, since they are local to some piece of code (e.g. a function, or a loop), and they communicate via function calls and return values.

ダイナミックアロケーションが必要なのみ時間は、特定のスコープよりも長く必要なデータがある場合です。そのようなデータは動的に割り当てられなければならず、最終的には不要になったときに解放される必要があります。

これの最も基本的な使用例は、典型的なリンクリストです。一般的な「挿入/消去/検索」リスト操作関数を使用する場合は、リストノードを任意のスコープに対してローカルにすることはできません。したがって、各ノードは動的に割り当てられなければならず、リスト操作関数は、もはやリストの一部ではないノードを解放することを保証しなければならない。

要約すると、変数の割り当ては根本的かつ主に scope の問題です。可能であれば、すべてを自動化し、何もする必要はありません。必要に応じて動的割り当てを使用し、必要に応じて手動で割り当てを解除してください。

ほとんどのプラットフォームでは、自動変数のサイズが動的変数のサイズよりもはるかに小さい制限になっているため(@ emliは、@Oliは言うとおり、動的割り当てを厳密にローカルコンテキストで使用することもできます)自動変数の利用可能な領域を超えると、通常、「パイルオーバーラン」などのカラフルな名前が付けられます。

5
追加された
可能であれば、動的割り当てを避けるためのアドバイスは+1。
追加された 著者 R..,
@OliCharlesworth:ああ、はい、別の良い点!編集されました。
追加された 著者 Kerrek SB,
malloc が適切ではないときの素晴らしい説明
追加された 著者 g33kz0r,
あなたがそれを説明した方法は間違いなく助けになりました。 $ x = "some string"; のPHPから来て、私は malloc を使用しようとしていました。それを、自動ではなく動的なものとして記述する方がはるかに意味があります
追加された 著者 cegfault,
アウトリビングスコープにならないダイナミックアロケーションの例は、スタックを壊す大規模な配列(例えば、100万の要素)が必要な場合です。
追加された 著者 Oliver Charlesworth,

一般的に、 malloc のすべての呼び出しは、 free に対応する one スコープ(つまり、関数やループとは関係ありません)。


*このルールの例外には、 strdup のような関数の使用が含まれますが、原則は同じです。
3
追加された
@xixonia:クラッシュは、あなたが期待するべきものではなく、最良のシナリオです。最悪の場合は、攻撃者のルートを与えています。
追加された 著者 R..,
@xixonia:完了!
追加された 著者 Oliver Charlesworth,
@ R ..、これだけで私はCに戻ってみたいと思う:)
追加された 著者 cwharris,
free(...)を2回呼び出すとクラッシュする可能性があることに注意してください。
追加された 著者 cwharris,

大まかに言えば、 malloc()によって返されたすべてのポインタは、最終的に free()に渡されなければなりません。変数をスコープに入れなくても、ポインタが指すメモリはを呼び出すまで割り当てられるため、 にポインタを格納する変数のスコープは影響を受けません> free()をクリックします。

2
追加された

まあ、mallocされたメモリの範囲は、プロセスが停止するまで(すなわち、OSがプロセスをクリーンアップするまで)、 mallocfree free を決して呼び出さないと、メモリリークが発生します。これは、あなたが実際に使用する前に free に渡すことができるアドレスが範囲外になるときに起こる可能性があります。つまり、車のキーを紛失したようなものです。車はまだありますが、 。あなたが得ているエラーは、 malloc を使って割り当てられなかったメモリへのポインタを関数が返すか、 free に渡すヌルポインタを返すためです。あなたはすることはできません。

1
追加された
厳密に言えば、Cの単語は「生涯」ではなく「保存期間」です。 :-)
追加された 著者 R..,
@OliverCharlesworth、oh snap fighting words ::ポップコーンポップコーン::
追加された 著者 user1717828,
あなたは「スコープ」ではなく「生涯」を意味します。スコープは、オブジェクトではなく識別子に適用されます。
追加された 著者 Oliver Charlesworth,
@ R ..:いいえ、私は本当に "生涯"を意味します。 6.2.4節2を参照のこと。
追加された 著者 Oliver Charlesworth,

アクセスしなくなったらメモリを解放する必要があります。アクセスする場合はメモリを解放しないでください。これはあなたに多くの痛みを与えるでしょう。

0
追加された

malloc(n)は、ヒープという名前のメモリロケーションからnバイトのメモリを割り当ててから、void型のポインタを返します。メモリは実行時に割り当てられます。一度メモリを動的に割り当てると、スコープはポインタ(またはポインタのアドレス)をポインタと一緒に保持している限り重要ではありません。例えば:

int* allocate_an_integer_array(int n)
{
    int* p = (int*) (malloc(sizeof(int)*n));
    return p;
}

この関数は単純にn個の整数に等しいヒープからメモリを割り当て、最初の場所へのポインタを返します。ポインタは、呼び出し元の関数で使用することができます。スコープは、ポインタがあなたと同じであれば問題ありません。

free(p)はヒープにメモリを返します。

あなたが覚える必要がある唯一の事は、あなたがそれを解放せず、そのアドレスの価値を失うかのようにそれを解放することです。メモリリークが発生します。 OSによれば、あなたは解放していないのでメモリを使用しているので、メモリリークが起こるからです。

同じメモリが別の目的のために他の時間に再び割り当てられるかもしれないので、あなたが再びそれを使用しないようにnullをポインタの値を設定するだけで解放した後....

だから、あなたがする必要があるのは注意することです。

それが役に立てば幸い!

0
追加された

メモリリークをしたくない場合は、メモリをmallocから解放する必要があります。

それは非常に扱いにくいことがあります。たとえば、//do some stuffcontinue がある場合、フリーはスキップされ、メモリリークが発生します。それは扱いにくいので、C ++にはshared_ptrがあります。 Cプログラマーの給与はC ++プログラマーよりも高いという噂があります。

ときどきメモリリークに気をつけません。メモリが実行の全期間中必要なものを保持している場合は、解放しないことを選択できます。例:環境変数の文字列。

PS: Valgrind は、メモリのバグを検出するのに役立つツールです。メモリリークに特に便利です。

0
追加された
私の同僚がライブラリコードでメモリリークを残すと、チケットを調達して修正するようにしています...
追加された 著者 Oliver Charlesworth,
いいえ、私たちは単に記憶を正しくクリアすることができます。
追加された 著者 Oliver Charlesworth,
生涯のために何かを自由にすることを怠ることは、実行の全体が非常に貧しい習慣であることです。まず、Valgrindの出力にエラーが発生します。
追加された 著者 Oliver Charlesworth,
同意する。しかし、私たちはそれで生きなければなりません。
追加された 著者 Cha Cha,
コードを書く唯一の人ではなく、ライブラリを使用しないでください。現実は同僚のコードです。依存しているライブラリがメモリを解放していない可能性があります。
追加された 著者 Cha Cha,
さて、あなたはポイントを持っています。私はputenv(strdup(...))のメモリを解放するように同僚に説得するつもりです。私はそれらを働かせようとします。ありがとうございました。
追加された 著者 Cha Cha,