2

重複の可能性:
C 配列のインスタンス化 - スタックまたはヒープの割り当て?

char ポインターを含む構造体を動的に割り当てる場合、実際の char ポインターはどうなりますか? どこに保管されていますか?

構造体が解放されると、char ポインターも一緒に解放されますか?

たとえば、次の構造体を考えてみましょう。

struct mix
{
    int a;
    float b;
    char *s;
};

typedef struct mix mix;

そして、それにメモリを割り当てる次のコード:

int main()
{
    mix *ptr = (mix*)malloc(sizeof(mix));

    ptr->a = 3;
    ptr->b = 4.5f;
    ptr->s = "Hi, there, I'm just a really long string.";

    free(ptr);

    return 0;
}

スタックに割り当てられた後、 ?*sと共に解放され*ptrます。動的に割り当てられていないため、実際にスタックに割り当てられていると想像できます(mallocに私が知らない機能がある場合を除く)。*sそして、解放の時点で「範囲外」になると思い*ptrます。それとも、完全に間違っていますか?:)

どうもありがとう!

4

6 に答える 6

6

char*指定されたメンバーのスペースは、への呼び出し後の残りのメンバー(戻り値をキャストする必要はありません)sとともにヒープに割り当てられます。割り当てられる文字列リテラルは、ヒープまたはスタックには割り当てられませんが、実際のバイナリの一部であり、静的な保存期間があります。したがって、この:mixmalloc()s

ptr->s = "Hi, there, I'm just a really long string.";

文字列リテラルのアドレスをに割り当てますptr->sptr->s文字列リテラル以外のものをポイントしたい場合は、malloc()それを記憶する必要があります。そして、すべてmalloc()の場合、free()その前にdでptr->sある必要があります(動的にメモリを割り当てることのみを指している場合)。free()ptrptr->s

の呼び出し後free()、間接参照ptrは未定義の動作です。

于 2012-10-18T09:23:12.367 に答える
4

mixで動的に割り当てる場合、実際には、構造データメンバーmalloc()を格納するためにメモリのブロックを割り当てています。mix

  • inta)_
  • a floatb
  • ()へのポインタchars

そして、あなたが電話するとき、あなたはただそのfree()ブロックを解放します。

したがって、文字列を割り当てるのではなく、文字列ポインタを割り当てるだけです。

文字列を動的に割り当てる場合は、明示的に(への別の呼び出しを使用してmalloc())行う必要があります。また、メモリリークを回避するには、を使用して文字列を明示的に解放する必要がありますfree()

于 2012-10-18T09:24:26.223 に答える
4

をmallocすると、メモリは構造体の他のメンバーに割り当てられたメモリと同じでptrあるポインタを含む、構造体のすべてのメンバーに割り当てられます。s

文字列リテラルをに割り当てているsので、通常は読み取り専用セクションに格納されていても問題ありません。mallocそれ以外の場合は、ptr->s同様にとする必要がありますfree。これは文字列リテラルなので、sここで解放する必要はありません(そうすることでUBになります)。

于 2012-10-18T09:24:28.267 に答える
2

mix* ptrスタックに割り当てられます。混合型の変数であるptrが指すコンテンツは、ポインターを含め、ヒープ上で動的に割り当てられますs

何も指さないことに注意してくださいs。ポインタは何の役にも立ちません。どこにでも割り当てることができる何かを指すように設定する必要があります。構造体が解放されても、それが指しているものはすべて解放されません。この場合、ROMに割り当てられた定数文字列リテラルを指すように設定するので、それについて心配する必要はありません。

于 2012-10-18T09:25:17.447 に答える
2
what happens with the actual char pointer? Where is it stored? 

char* も他のメンバーと同様に、いくつかのバイトを使用します (他のポインターと同様に、64 ビット マシンでは 8 バイトを使用します)。あなたの場合、ヒープ内のその構造体インスタンスにメモリを割り当てています。したがって、このポインタのメモリも、その構造体インスタンスに割り当てられている同じヒープ ブロックに割り当てられます。

このコードを検討してください。これにより、char* がどこにあるかがわかります。

#include <stdio.h>    
typedef struct
{
    int a;
    float b;
    char *s;
}mix;    
int main()
{

printf("\n%d ,float:%d, int:%d, char*:%d", sizeof(mix), sizeof(float), sizeof(int), sizeof(char*));

return 0;
}

したがって、この構造体のサイズは 16 バイトです。4 バイトの整数、4 バイトの浮動小数点数、および 8 バイトの char* で構成されます。(64ビットOSでは、OSが32ビットの場合、char*は4バイトになります。)

And once the struct is freed, is the char pointer freed along with it?

通常、char* が指すブロックは解放されません (malloc() によって割り当てられたブロックを指している場合)。構造ブロックのみが解放されます。free() には、平和的な割り当て解除のために割り当て中に返される有効なアドレスが必要であることがわかっています。その char* を解放せずに解放すると、メモリ リークが発生します。

しかし、あなたの場合"Hi, there, I'm just a really long string.";

上記の文字列は、プログラムの読み取り専用セクションに割り当てられた文字列リテラルです。

使用するgcc -S Yourprogram.c

これにより、.s ファイルが生成されます。.read_onlyこの文字列のセクションを見ることができます。したがって、構造インスタンスを削除しても、メモリ リークは発生しません。読み取り専用のアドレスを指しているだけだからです。この文字列にメモリをまったく割り当てていません。

于 2012-10-18T09:46:22.927 に答える
2

*s はスタックに割り当てられていますか

*s(つまり、ポインターを逆参照した結果s) はまったく割り当てられません。に続くのmallocptr->s、初期化されていないポインタです。それは何も指しておらず、*(ptr->s)そうするまで式は未定義の動作をしますptr->s = "Hi, etc"

ptr->s文字列リテラルを指すように初期化すると、文字列リテラル*(ptr->s)の最初の文字になるため、実行可能ファイルの一部のデータ セクションに存在する可能性があります。sizeof(mix)構造体のバイト (おそらく 32 ビット実装では 12 バイト)以外には何も動的に割り当てられません。

于 2012-10-18T09:34:59.073 に答える