3

私は C で非常に単純な連結リスト ノード構造を作成しました。いくつかの一般的なポインター データと次のノード構造へのポインターを使用します。リンクされたリストノードを取得し、それとそれがリンクしている他のノードを削除する関数があります。現在、次のように作成されています。

void freeLinkedList(LinkedListNode *node)
{
   LinkedListNode *currentNode = node;
   LinkedListNode *previousNode = NULL;
   do
   {
        free(currentNode->data);

        previousNode = currentNode;
        currentNode = currentNode->next;

        printf("Freeing node... %s\n", previousNode->name);
        free(previousNode);
        printf("freed it!\n");
    } while (currentNode != NULL);

    printf("Deleted node and all referencing nodes!");
}

関数で指定されたノードから非常に単純にトラバースし、引き続きポインター データを削除し、次のノード (存在する場合) をポイントし、前のノードのメモリを削除します。これは予測どおりに機能します...ただし、場合によってのみです。

実際の LinkedList 構造は次のようになります。

typedef struct LinkedListNode {
    void *data;
    struct LinkedListNode *next;
    char name[50];
} LinkedListNode;

このように動的に割り当てられた構造体の場合、関数は完全に機能します。

LinkedListNode *myNode1 = malloc(sizeof(struct LinkedListNode));
LinkedListNode *myNode2 = malloc(sizeof(struct LinkedListNode));
LinkedListNode *myNode3 = malloc(sizeof(struct LinkedListNode));
strcpy(myNode1->name, "Node1");
myNode1->data = NULL;
myNode1->next = myNode2;

strcpy(myNode2->name, "Node2");
myNode2->data = NULL;
myNode2->next = myNode3;

strcpy(myNode3->name, "Node3");
myNode3->data = NULL;
myNode3->next = NULL;

freeLinkedList(myNode1); // CALLING DELETE FUNCTION HERE

しかし、ヒープメモリではなく自動スタックメモリに割り当てられた構造で関数を使用すると、次のようになります。

LinkedListNode myNode1 = {NULL, NULL, "Node1"};
LinkedListNode myNode2 = {NULL, NULL, "Node2"};
LinkedListNode myNode3 = {NULL, NULL, "Node3"};

myNode1.next = &myNode2;
myNode2.next = &myNode3;

freeLinkedList(&myNode1); // CALLING DELETE FUNCTION HERE

関数の次の行でSIGSEGV - セグメンテーション違反が発生します。

free(previousNode);

このエラーは、最後のノードの free 関数でのみ発生します。つまり、出力には次のように表示され ます。

その後、クラッシュします。

しかし、非常に面白いことに、これまでのところ、上記の例を使用してしか経験していません。私が言うなら、次のようにローカルの LinkedListNode 構造体をもう 1 つ宣言します。

LinkedListNode myNode1 = {NULL, NULL, "Node1"};
LinkedListNode myNode2 = {NULL, NULL, "Node2"};
LinkedListNode myNode3 = {NULL, NULL, "Node3"};
LinkedListNode myNode4 = {NULL, NULL, "Node4"};

myNode1.next = &myNode2;
myNode2.next = &myNode3;

freeLinkedList(&myNode1);

関数は実際に機能し、期待どおりにすべてを行います。

なぜこれができるのかを考えようと数時間試みましたが、私は単に困惑しています. スタックに割り当てられたメモリを解放しようとすることと関係がありますか?

4

1 に答える 1