在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()。
我是 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()。