在C中取消分配动态分配的结构内存

De allocating dynamically allocated memory of structure in C

我是 C 编程的新手,我想学习指针和动态内存分配,所以决定在 C 中实现链表。我在函数 deleteFromMiddle() 中遇到问题,在那里我得到 Sigtrap 信号并且程序结束。你能指出我在这里做错了什么吗?

PS。我使用的不是下一个,而是上一个节点指针。

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

// Implementing linked list
// Linked list should have the following operations
// Insert @begining, @middle and @end
// Display linked list should iterate thru each node and print the  content.
// remove a node shall remove the node specified by the address



/*
 * At first Linked list should contain a initial node whose previous node shall be set to null and content
 * should be set to "initial".
 * This implementation is of Singly linked list.
*/


/*
 * Defining a struct for Node. 
 */

 int NODE_COUNT = 0; // Counts number of nodes existing in our linked list.
 static struct Node {
     struct Node *prev; // points to Previous Node.
     void *content;
 };

 // Initial node. 
 struct Node initialNode;

 // Pointer to the last Node.
 static struct Node *lastNode;

 // First insertion
int firstTime=1;

 // Initial node. 
 struct Node initialNode = {.prev=NULL,.content=(void*)&("INITIAL NODE")};


/*
 * Defining Insertion operation
 */

 /*
  * This function adds a node to the beginning of linked list.
  * This does not however adds before Initial node. this is not circular linked list. 
  */

void insertAtStart(struct Node * nodeToBeAdded){
    if(firstTime){
        nodeToBeAdded->prev=&initialNode;
        lastNode=nodeToBeAdded;
        firstTime=0;
        NODE_COUNT++;
    }else{

        int i=0;

        // Iterate through all the nodes until we get the first Node whose Prev is set to initial Node.
        // This step is not necessary if the nodes are doubly linked.
        struct Node *currentNode = lastNode;

        // This whole thing can be replaced by a recursive function.
        while(i<NODE_COUNT){
            if(currentNode->prev==&initialNode){
                // If current Node's previous Node is initial Node
                // Then set new Node's prev to initial Node and
                // current Node's prev to new Node.
                // Then break the loop
                 nodeToBeAdded->prev=&initialNode;
                 currentNode->prev=nodeToBeAdded;
                 NODE_COUNT++;

                 break;
            }else{
                // If current Node's previous is not Initial Node
                // Then make current Node's previous as current Node.
                currentNode = currentNode->prev;

            }
            i++;

        }

    }

}

/*
 * This function inserts Node in the middle of the list provided the Node
 * before which our node has to be inserted.
 */ 
 void insertAtMiddle(struct Node * nodeToBeAdded, struct Node* beforeNode){
     // If this is first insertion then add it after initial Node
      if(firstTime){
        printf("Inside firstTime @insertAtStart\n");
        nodeToBeAdded->prev=&initialNode;
        lastNode=nodeToBeAdded;
        firstTime=0;
        NODE_COUNT++;
    }else
        // If not then add it before beforeNode
    {
      // In order to insert in middle, atleast there should be a single new node plus initial node.  
     if(NODE_COUNT>0){
         // Make node to be added's prev to whatever the previous node of beforeNode
         if(beforeNode!=&initialNode){
         nodeToBeAdded->prev= beforeNode->prev;
         // Make before node's prev as node being inserted.
         beforeNode->prev=nodeToBeAdded;
         NODE_COUNT++;
         }else{
             printf("Cannot insert before initial node.");
         }
         }
     }   
    }

 /*
 * This function inserts Node at the end of the list provided the Node
 * before which our node has to be inserted.
 */ 
 void insertAtEnd(struct Node * nodeToBeAdded){
     // If this is the first insertion then add after initial Node
      if(firstTime){
        printf("Inside firstTime @insertAtStart\n");
        nodeToBeAdded->prev=&initialNode;
        lastNode=nodeToBeAdded;
        firstTime=0;
        NODE_COUNT++;
    }else{// Else add after lastNode.
         nodeToBeAdded->prev= lastNode;
         lastNode=nodeToBeAdded;
         NODE_COUNT++;
         }
}




/*
 *  This function deletes the first node after initial node.
 * 
 */

void deleteFromStart(){
    int i =0;

    struct Node * currentNode, * prevNode;

    if(NODE_COUNT==1){
        //Do nothing
        printf("There is no nodes in the linked list.");
    }
    else if(NODE_COUNT==1){
        free(lastNode);
    }else{

    currentNode = lastNode->prev;
    prevNode = lastNode;

    while(i<NODE_COUNT){
        if(currentNode->prev==&initialNode){
            //de allocate currentNode memory                
                prevNode->prev=&initialNode;
                NODE_COUNT--;
                free(currentNode);
            break;
        }else{
            prevNode = currentNode;
            currentNode=currentNode->prev;
        }

    }
    }

}

/*
 *  This function deletes the last node.
 * 
 */

void deleteFromEnd(){
    if(NODE_COUNT>1){
        struct Node* toBeCleared = lastNode;
        lastNode = lastNode->prev;
        free(toBeCleared);
        NODE_COUNT--;
    }else{
        printf("List is empty!");
    }
}

/*
 *  This function deletes node before the specified node.
 * 
 */

void deleteFromMiddle(struct Node* ptr){
    if(ptr==&initialNode){
        printf("There is no node infront of Initial Node. Ha! try harder.");
    }else if(NODE_COUNT==2){
        printf("There is only one node. and before that node is initial node, which cannot be deleted.");
    }else{
        struct Node* nodeToBeDeleted = ptr->prev;
        ptr->prev=ptr->prev->prev;
        free(nodeToBeDeleted);
        NODE_COUNT--;        
    }
}


/*
 * Display LinkedList content. 
 */

 void displayList(void(*ptr)(void*)){

     if(NODE_COUNT==1){
         printf("Oopsie there is no node in linked list.");
     }else{
     int i=0;

     struct Node *currentNode = lastNode;
     printf("Initial node address:  %.4x\n", &initialNode);
     printf("Last node address:  %.4x\n", lastNode);
     while(i<NODE_COUNT){
         printf("Node Address: %.8x ", currentNode);
         printf("Node Prev Address: %.8x ", currentNode->prev);
         ptr(currentNode->content);
         currentNode=currentNode->prev;
         i++;
     }
     }


 }

 void convert(void * content){
     printf("Content: %s \n", (char*)content);
 }

struct Node * createANode(void* content){
    struct Node* ptr = (struct Node*)malloc(sizeof(struct Node));
    ptr->content=content;
    return ptr;
}
 int call(){

     insertAtStart(createANode((void *)"first node"));
     insertAtStart(createANode((void *)"second node"));
    insertAtStart(createANode((void *)"third node"));


     struct Node * fourthNode = createANode((void *)"fourth node");

    insertAtStart(fourthNode);

    displayList(&convert);
    insertAtMiddle(createANode((void *)"fifth node"),fourthNode);
    printf("\nAfter adding one node in middle.\n");
    displayList(&convert);

    insertAtEnd(createANode((void *)"sixth node"));
    insertAtEnd(createANode((void *)"seventh node"));

    displayList(&convert);
    printf("NoDE cOUNT  : %d\n", NODE_COUNT);


    deleteFromStart();
    displayList(&convert);
    printf("NoDE cOUNT  : %d\n", NODE_COUNT);

    deleteFromEnd();
    displayList(&convert);
    printf("NoDE cOUNT  : %d\n", NODE_COUNT);

    deleteFromMiddle(fourthNode);
    displayList(&convert);
    printf("NoDE cOUNT  : %d\n", NODE_COUNT);

    getch();
    return 0;
 }

您在 deleteFromMiddle() 中存在错误。

您对 deleteFromMiddle() 的调用正试图删除 fourthNode,它是列表中的第一个节点。这意味着 fourthNode->prev 是 initialNode 的地址(不是动态分配的)。

在 deleteFromMiddle() 中,您在 initialNode (ptr->prev) 上调用 free(),这是不允许的,因为它不是动态分配的。

解决此问题的方法是改为在 ptr 上调用 free()。