web-dev-qa-db-ja.com

C-構造体の解放

この構造体があるとしましょう

typedef struct person{
    char firstName[100], surName[51]
} PERSON;

そして、私はmallocでスペースを割り当てて、いくつかの値で埋めています

PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));
strcpy(testPerson->firstName, "Jack");
strcpy(testPerson->surName, "Daniels");

その構造体が取ったすべてのメモリを解放するための正しい安全な方法は何ですか? 「free(testPerson);」です十分ですか、または各構造体の属性を1つずつ解放する必要がありますか?

それは別の質問につながります-構造はどのようにメモリに保存されますか?奇妙な振る舞いに気付きました-構造体のアドレスを出力しようとすると、それは最初の属性のアドレスと同じです。

printf("Structure address %d == firstName address %d", testPerson, testPerson->firstName);

つまり、このfree(testPerson)はこのfree(testPerson-> firstName)と等しくなければなりません。

それは私がやりたいことではありません。

ありがとう

44
user10099

簡単な答え:free(testPerson)で十分です。

malloccalloc、またはreallocを使用してメモリを割り当てた場合にのみ、free()を使用できることに注意してください。

あなたの場合、testPersonに割り当てられたメモリしかないので、それで十分です。

_char * firstname , *last surName_を使用した場合、その場合は名前を保存するためにメモリを割り当てておく必要があります。そのため、各メンバーを個別に解放する必要があります。

また、逆の順序にする必要がある点もここにあります。つまり、要素に割り当てられたメモリは後で行われるので、free()最初にオブジェクトへのポインタを解放します。

各要素を解放すると、次のデモが表示されます。

_typedef struct Person
{
char * firstname , *last surName;
}Person;
Person *ptrobj =malloc(sizeof(Person)); // memory allocation for struct
ptrobj->fistname = malloc(n); // memory allocation for firstname
ptrobj->surName = malloc(m); // memory allocation for surName

.
. // do whatever you want

free(ptrobj->surName);
free(ptrobj->firstname);
free(ptrobj);
_

この理由は、最初にptrobjを解放すると、firstnameおよびsuNameポインターによって割り当てられたメモリであるメモリリークが発生するためです。

59
Omkant

struct配列で構成されるcharを定義したため、2つの文字列areは構造であり、structを解放するだけで十分です。 structを解放するが、配列を保持する方法。その場合は、struct { char *firstName, *lastName; }、ただし、名前ごとにメモリを個別に割り当て、いつ解放するかthatメモリの問題を処理する必要があります。

余談:structが解放された後も名前を保持したいreasonがありますか?

5
dmckee

まず、以下の場合にメモリを定義して割り当てるときに割り当てるメモリの量を知っておく必要があります。

   typedef struct person{
       char firstName[100], surName[51]
  } PERSON;
  PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));

1)sizeof(PERSON)は151バイトを返します(パディングは含まれません)

2)151バイトのメモリがヒープに割り当てられます。

3)解放するには、free(testPerson)を呼び出します。

しかし、あなたの構造を

  typedef struct person{
      char *firstName, *surName;
  } PERSON;
  PERSON *testPerson = (PERSON*) malloc(sizeof(PERSON));

それから

1)sizeof(PERSON)は8バイトを返します(パディングを含みません)

2)malloc()またはcalloc()を呼び出して、firstNameとsurNameにメモリを割り当てる必要があります。好む

        testPerson->firstName = (char *)malloc(100);

3)解放するには、構造体を解放するよりもまず構造体のメンバーを解放します。すなわち、free(testPerson-> firstName); free(testPerson-> surName); free(testPerson);

4
Viswesn

この方法では、フィールドは構造の一部として割り当てられる静的サイズの配列であるため、構造を解放するだけで済みます。これは、表示されるアドレスが一致する理由でもあります。配列はその構造の最初のものです。フィールドをchar *として宣言した場合、手動でmallocし、同様にそれらを解放する必要があります。

3
MK.

MallocとFreeはペアにする必要があります。

mallocは、Personに十分な大きさのメモリチャンクを取得しました。

解放すると、mallocに「ここ」から始まるメモリが不要になったことを伝え、割り当て量を認識して解放します。

電話するかどうか

 free(testPerson) 

または

 free(testPerson->firstName)

free()が実際に受信するのはアドレスであり、同じアドレスで、どちらを呼び出したかはわかりません。ただし、free(testPerson)を使用すると、コードがはるかに明確になります-with mallocと明らかに一致します。

2
djna

動的に割り当てられていない型を解放することはできません。配列は構文的に似ています(int* x = malloc(sizeof(int) * 4)は_int x[4]_と同じ方法で使用できます)が、free(firstName)を呼び出すと後者のエラーが発生する可能性があります。

たとえば、次のコードを使用します。

_int x;
free(&x);
_

free()は、ポインターを受け取る関数です。 _&x_はポインターです。このコードは、単に機能しない場合でも、コンパイルされる場合があります。

すべてのメモリが同じ方法で割り当てられているふりをすると、xは定義で「割り当て」られ、2行目で「解放」され、スコープの終了後に再び「解放」されます。同じリソースを2回解放することはできません。エラーが発生します。

これは、特定の理由により、プログラムを終了しないとxのメモリを解放できないという事実すら言及していません。

tl; dr:structを解放するだけで大​​丈夫です。 Do n't配列でフリーコール;動的に割り当てられたメモリでのみ呼び出します。

2
Undeterminant

freeは十分ではありません。freeはメモリを未使用としてマークするだけで、構造データは上書きされるまで存在します。安全のため、ポインタをNULLの後にfreeに設定します。

例:

if (testPerson) {
    free(testPerson);
    testPerson = NULL;
}

structは配列のようなもので、メモリのブロックです。オフセットを介してstructメンバーにアクセスできます。最初の構造体のメンバーはオフセット0に配置されるため、最初の構造体のメンバーのアドレスは構造体のアドレスと同じです。

2
sdao