2017-03-19 8 views
0

さまざまなケースを試してCでリンクリストを覚えようとしていますが、質問があります。私はこのコードを書いており、動的に割り当てられたメモリを解放する正しい方法がわからない。ちょうど自由(S);または私は無料で書く必要がありますか?同様に、これらの2つのコマンドの順序は重要ですか?また、それ以外は、このコードは正しく書かれていますか?あなたが気にしないならば、私は完全な説明をしたい、私は5年間何もコード化していない。リンクリストの使用中にCで動的に割り当てられたメモリを解放する

#include <stdlib.h> 
#include <stdio.h> 

typedef char StackType; 

typedef struct StackNodeTag 
    {StackType T; 
    struct StackNodeTag *Link; 
    } StackNode; 

typedef struct StackTag 
    {struct StackNodeTag *Top; 
    } Stack; 

typedef Stack *StackPointer; 

int main (void) 
    {StackPointer S; 

    S = malloc (sizeof (Stack)); 
    S->Top = malloc (sizeof (StackNode)); 

    S->Top->T = 'c'; 
    S->Top->Link = NULL; 

    free (S->Top); 
    free (S); 

    return 0; 
    } 
+0

へのアクセス方法を変更しますと、細かい音が鳴ります。最初に 'S'を解放すると、' S-> Top'が無効になる可能性があるので、問題を発注してください。 –

答えて

0

このコードは正しいです。すべてのmalloc()コールには対応するfree()コールが必要です。したがって、ここではSとTopの両方のフリーコールが必要です。

ほとんどの場合、free()の呼び出しの順番は関係ありません。すべてのmalloc()呼び出しはポインタを返します。 mallocから返されるのと同じポインタで自由に呼び出す限り、任意の順序でデータを解放することができます。

ただし、トップへの参照はSを介しているため、この場合はfree()呼び出しの順序が重要です。Sを解放すると、Sで参照される構造体に格納されているデータ。

多くの実装では、解放した構造体のデータに直接アクセスすると、そのデータは解放され、データはそこに残ります。しかし、データをそのまま残すという保証はないので、これは悪い習慣です。このため、無料(S->トップ)への電話は無料(S)の前に来なければなりません。

たとえば、このデータを解放するには、1)一時変数にStackNodeポインタを保存し、2)空きSを、3)空きTopを一時変数を使用して保存します。しかし、これを書いたやり方は、より簡単です。

1

はい、あなたはmallocまたは同様の機能を割り当てられたすべてのものを解放しなければならない、との順序は問題ありません。

の中に動的に割り当てられたアイテムがあるので、内にあるから、内部から解放する必要があります。 をS->Topの前に解放すると、処理中にmallocデータを含むメモリを解放するため、メモリリークが発生する可能性があります。

1

mallocへのコール数は、freeへのコール数と同じである必要があります。

あなたが持っているものは正しく動作します。あなたが自由にしたいメモリが到達可能であることを確認するだけでよいのです。たとえば、コード内でfree(S)を最初に実行した場合は、Sは有効なメモリをポイントしないため、free(S->Top)を正常に呼び出すことはできません。

0

あなたのmallocとfreeの使用は正しいですし、動作する唯一の順序です。

Sが指すスタックは、要素Topにアクセスまたは割り当てられる前に存在する必要があります。さらに、SがS-> Topの前に解放されていれば、S-> Topが指すメモリが孤立します。スタックがアクセスしたり解放したりすることはありません(スタックがSによって指し示されていればS-> Topを解放することはできません)存在する)。

コードを見やすくするためにいくつかの文章的な問題を修正することもお勧めします。

// Original 
int main (void) 
{StackPointer S; 
    .. 
} 

これは、開き括弧と同じ行のコードでは読みにくいです。理解できないわけではなく、一見して理解できないだけです。

// Easier to read 
int main(void) 
{ 
    StackPointer S; 
    .. 
} 

/* Alternate Style, many will say to use 
    the above for functions and this for all 
    other bracket notation (structs/unions, control flow) */ 
int main(void) { 
    StackPointer S; 
    .. 
} 

これらは、よく使用される2つのスタイルです。

typedef Stack *StackPointer; 
... 
StackPointer S; 

これは非常に不必要で、読者はStackPointerの内容を調べる必要があります。

Stack *S; 

これはtypedefを必要とせず、SがStack型へのポインタであることがすぐに分かります。

。 (必要であれば)

さらに、スタックはおそらく常に存在するよう、あなたは静的に作成することができます。これはまた、あなたがそれのメンバー

修正コード

#include <stdlib.h> 
#include <stdio.h> 

typedef char StackType; 

typedef struct StackNodeTag { 
    StackType T; 
    struct StackNodeTag *Link; 
} StackNode; 

typedef struct { 
    StackNode *Top; 
} Stack; 

int main (void) 
{ 
    Stack S; 

    S.Top = (StackNode *) malloc(sizeof(StackNode)); 

    S.Top->T = 'c'; 
    S.Top->Link = NULL; 

    free (S.Top); 

    return 0; 
} 
関連する問題