2016-06-14 4 views
0

私はCプログラミングの基本を学んでおり、それはかなり奇妙で困難です。特に、動的メモリ割り当て、ポインタおよび同様のもの。私はこの機能に着目し、何が間違っているのかをよく理解していません。関数でmallocを使うのはいつですか?

char *strdup(const char *p) 
    { 
     char *q; 
     strcpy(q, p); 
     return q; 
    } 

私はmallocとfree Qにあると思います。しかし関数 "return q"。それはそれがそれ自身の記憶にq値を記憶することを意味しない。したがって、関数の実行後もデータは保存されますか?

mallocを使用するのが適切なのはいつですか?私が今まで理解しているように、関数内で宣言された変数が他の場所で使用される必要があるたびに、新しい変数をmallocする必要があります。本当? mallocが必要な他の状況はありますか?

+0

まあ、 'strcpy'の呼び出しを見てください。 'p'が指す文字列を' q'が指す配列にコピーしようとしています。 'q'は配列を指すように初期化されていません。これにはガーベッジ・バリューが含まれているため、これを呼び出すとメモリが破壊されます。まず、 'malloc'が返すもののような適切な記憶域のアドレスに' q'を設定する必要があります。そのときだけ、そのターゲットに書き込むことができます。シンプル。 –

+0

qはアドレスですが、初期化されていません。 strcpyはデータを取得してqで指定された場所に配置しようとしていますが、qは有効なものを指していません。 mallocを呼び出す(そして結果をqに代入する)と、qはデータを置く場所を指します。 –

+0

*本物の問題は、あなたが生涯について知る必要があるということです。残念なことに、ほとんどのチュートリアルでは重要な問題ではなく、構文のみを教えています。 – o11c

答えて

4

私の個人的な規則は:オブジェクトがスタックに置くには大きすぎる、および/または現在のブロックのスコープ外になければならないときに使用してください。malloc()です。あなたのケースでは、私は信じて、次のような何かをする必要があります

char *strdup(const char *p) 
{ 
    char *q; 
    q = malloc(strlen(p) + 1); 
    if(NULL != q) 
     strcpy(q, p); 
    return q; 
} 
5

Qの型がポインタで、ポインタはアドレスを保持 - ので、あなたが戻ってきていることは、ポインタを保持しているアドレスです。

あなたはそのポインタに有効なアドレスを与えるまで、それは誰が知っているのかを指摘します。あなたが所有していても所有していなくてもよく、アクセスする権利があります。したがって、strdupコールは、pで保持されているアドレスから、おそらく所有していない場所に文字列をコピーします。

mallocを最初に実行してqをmallocの結果として与えた場合、qは有効なアドレスを保持し、あなたのstrdupはあなたが所有していたメモリにコピーを置きます(malloc'd十分なスペース文字列の場合は、pのstrlenがどれだけ必要なのかを伝えます)。

qを返すと、発信者にもアドレスが与えられます。そのアドレスのコードは、そこに置かれた文字列を見ることができます。将来のコードがそのアドレスを解放することになっていたら、それが空中にあるのです。それはまったく何でもかまいません。

したがって、あなたが保持しているアドレスを返す前にqを解放することは望ましくありません。発信者に準備が整うと、発信者にそのアドレスを解放させる必要があります。

mallocの場合は、関数が完了した後でも実行可能なアドレスを返す場合は、mallocする必要があります。呼び出し元にローカル変数のアドレスを与えます悪いこと:関数が返ってきたらメモリは解放され、もう所有していない。

mallocのもう一つの典型的な使い方は、ツリーやリストのような動的なデータ構造を構築することです。必要なメモリ量を知ることができないので、必要に応じてリストやツリーを構築し、構造内の各ノードのメモリを増やします。

0

malloc(X)は、再生するヒープ上に(サイズがXバイト)スペースを作成します。これらのデータに書き込むデータは、関数が返ったときにそのまま残ります。その結果、strdup()関数がヒープ上のその領域に書き込んだ内容を読み取ることができます。

free()は、ヒープ上の領域を解放するために使用されます。 malloc()またはrealloc()コールの結果としてのみ取得したこの関数へのポインタを渡すことができます。この機能データをクリアしないことがあり、それだけでmalloc()への後続の呼び出しがあなただけ解放された同じ空間のアドレスを返すことを意味します。これらはすべて定義された実装であり、信頼されるべきではないので、私は「may」と言います。 qpから一つあなたが書いたコードの一部で

strcpy()関数コピーバイト1が位置はq(およびそれのコピーも\0)によって指さで\0を見つけるまで。データをどこかに書き込むには、書き込むデータに最初にスペースを割り当てる必要があります。そのため、malloc()を呼び出してそこにデータを書き込む方法もあります。まあ

free()を呼び出すと、あなたが終了をプログラムするとき、あなたのOSがmalloc()によって割り当てられたスペースを再利用しますよう必須ではありませんしかし限り、あなたのプログラムが実行されるように、あなたはあなたがする必要があるより多くのスペースをocupyingすることができる - と、それは悪いですあなたのプログラムのために、他のプログラムのために、OSと宇宙のために全体として。

0

私はmallocとfree qをしなければならないと思います。しかし関数 "return q"。それはそれがそれ自身の記憶にq値を記憶することを意味しない。したがって、関数の実行後もデータは保存されますか?

いいえ、データは保存されません。実際、あなたのポインタqが割り当てられていない状態で使用されていると、問題が発生することがあります。また、この関数の実行が完了すると、変数char * qが破棄されます。

@ Michaelの答えで示唆されているようにデータをコピーする前にポインタqにメモリを割り当てる必要があります。しかし、この関数でデータを返すと、割り当てられたメモリを手動で解放する必要があります。原因メモリリーク

使用することが適切である

char *strdup(const char *p) // From @Michael's answer 
{ 
    char *q; 
    q = malloc(strlen(p) + 1); 
    if(NULL != q) 
     strcpy(q, p); 
    return q; 
} 

void someFunction() 
{ 
    char* aDupString = strdup("Hello World!!!"); 
    /*... somecode use aDupString */ 
    free(aDupString); // If not freed, will cause memory leaks 
} 
を(メモリが割り当てられたが、何のポインタを使用すると、割り当てられたメモリのチャンクを参照していないので、プログラムの実行全体にアクセスできなくなりますが存在している状況) malloc? mallocが必要な他の状況はありますか?

以下の状況で使用することが適切である:

1>配列の使用サイズは、コンパイル時に知られていません。

2>サイズの柔軟性が必要です。たとえば、関数は小さなデータサイズと大きなデータサイズで動作する必要があります。 (データ構造のようなリンクリスト、スタック、キュー、などなど)

私がこれまで理解したように、私は新しい変数私は関数内で宣言された変数がすることを必要とするたびにをmallocしなければならないということです他の場所で使用されています。本当?

私はこれが部分的に真実だと思います。あなたが何をしようとしているかによって、mallocを使って周りを回る方法があるかもしれません。たとえば、あなたのストルードは次のように書き直すこともできます:

void strdup2(const char *p, char* strOut) 
{ 
    // malloc not require 
    strcpy(strOut, p); 
} 

void someFunction() 
{ 
    char aString[15] = "Hello World!!!"; 
    char aDupStr[sizeof(aString)]; 
    strdup2(aString, aDupStr); 

    // free() memory not required. but size is not dynamic. 
} 
関連する問題