[英]Segmentation Fault Error in C
嗨,我是C語言的新程序員,我在鏈表程序中遇到了段錯誤,我想知道是否有人可以幫助我。 我已經在下面發布了我的代碼...如果您需要更多信息,我會發布它。 謝謝。
#include "list.h"
//+-------------------------------------------------------------
//+ CREATE NODE
//+
//+ Allocate memory for a node of type struct node and
//+ initialize it with d. Return a pointer to the new node.
//+-------------------------------------------------------------
struct node* createNode(int d){
struct node* newNode = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called newNode
newNode->item = d; //newNode's data is the value stored in 'd'
newNode->next = NULL; //sets the pointer to the next node to NULL
return newNode; //return the new node created
}
//+-------------------------------------------------------------
//+ INSERT HEAD NODE
//+
//+ Insert Node n in front of the head of the list, and set
//+ n to be the new head of the list.
//+-------------------------------------------------------------
void insertHead(struct node **headRef, struct node *n){
struct node* newNode = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called newNode
newNode->item = n->item; //newNode's data is assigned the value of the parameter node n''
newNode->next = *headRef; //since we are inserting the node at the head we set the next node to be the head reference
*headRef = newNode; //and then we assign the head reference to the new node created, thus, inserting the head node
}
//+-------------------------------------------------------------
//+ INSERT TAIL NODE
//+
//+ Insert Node n at the tail of the LinkedList.
//+-------------------------------------------------------------
void insertTail(struct node **headRef, struct node *n){
struct node* newNode = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called newNode
newNode = *headRef; //the new node is now the head reference
while(newNode->next != NULL) //while the next node is not equal NULL
newNode = newNode->next; //set the newNode to the next node (this finds the last node)
struct node* tmp = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called tmp
tmp->item = n->item; //the data of tmp is assigned the data of the parameter node 'n'
tmp->next = NULL; //the node following tmp is set to NULL
newNode->next = tmp; //tmp is now set to the next node, thus, becoming the last node i.e. the tail
}
//+-------------------------------------------------------------
//+ COUNT NODES IN LINKED LIST
//+
//+ Count the # of nodes that are part of the LinkedList.
//+-------------------------------------------------------------
int countNodes(struct node *headRef){
int counter = 0; //create a counter variable to store the number of nodes
struct node* current = headRef; //create a new node and assign it the reference to the head node
if(headRef = NULL) return 0; //if the head is NULL, return 0 (no nodes if no head)
while(current != NULL){ //while the current node is not NULL
counter++; //increment the counter
current = current->next; //and move on to the next node, thus, adding 1 to the counter with each node passed
}
return counter; //return the total number of nodes, stored in counter
}
//+-------------------------------------------------------------
//+ FIND NODE
//+
//+ Return the first node that has item = val, return NULL
//+ otherwise.
//+-------------------------------------------------------------
struct node* findNode(struct node *head, int val){
struct node* tmp = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called tmp
*tmp = *head; //node tmp is now referring to the head node of the list
while(tmp != NULL) //while the tmp node is not equal to NULL
{
if(tmp->item == val){ //if the data of the tmp node is equal to the value sent as parameter
return tmp; //return the tmp node
}else{
return NULL; //otherwise, return NULL
}
tmp = tmp->next; //set the tmp node to the next node in the list (traversing)
}
}
//+-------------------------------------------------------------
//+ DELETE NODE
//+
//+ Delete node n from the list and free memory allocated to n.
//+-------------------------------------------------------------
void deleteNode(struct node **headRef, struct node *n){
struct node* toBeDeletedNode = malloc(sizeof(struct node)); //create and allocate space in memory for a new node called toBeDeletedNode
toBeDeletedNode = findNode(*headRef, n->item); //toBeDeletedNode is set to equal the node findNode() returns
//this node should be the node with its data = to the data of the parameter node n
free(toBeDeletedNode); //delete node toBeDeletedNode references and free the space allocated it
}
這是測試文件。
#include "list.h"
#include <assert.h>
#include <sys/types.h>
#include <stdio.h>
// create and insertHead
void test1()
{
struct node *headRef=NULL;
struct node *nptr = NULL;
int h=0;
while(h<5)
insertHead(&headRef,createNode(h++));
h = 0;
for (nptr = headRef; nptr != NULL; nptr = nptr->next, h++)
assert(nptr->item == (4 - h) );
assert(h==5);
printf("HAHA");
}
// create and insertTail
void test2()
{
struct node *headRef=NULL;
struct node *nptr = NULL;
int h=0, t=0;
while(h<5)
insertTail(&headRef,createNode(h++));
h = 0;
for (nptr = headRef; nptr != NULL; nptr = nptr->next, h++)
assert(nptr->item == h);
assert(h==5);
printf("HAHA");
}
// countNodes
void test3()
{
struct node *headRef=NULL;
struct node *nptr = NULL;
int h=0, t=0;
while(h<50)
insertTail(&headRef,createNode(h++));
h = 0;
for (nptr = headRef; nptr != NULL; nptr = nptr->next, h++)
assert(nptr->item == h);
assert(countNodes(headRef) == 50);
}
// findNode
void test4()
{
struct node *headRef=NULL;
struct node *nptr = NULL;
int h=0;
nptr = findNode(headRef, 1);
assert(nptr == NULL);
while(h<50)
insertTail(&headRef,createNode(h++));
nptr = findNode(headRef, 10);
assert(nptr != NULL);
assert (nptr->item = 10);
nptr = findNode(headRef, -10);
assert(nptr == NULL);
}
// deleteNode
void test5()
{
struct node *headRef=NULL;
struct node *nptr = NULL;
int h=0;
while(h<5)
insertTail(&headRef,createNode(h++));
h = 0;
while(h<5) {
nptr = findNode(headRef, h);
assert(nptr != NULL);
deleteNode(&headRef, nptr);
assert(findNode(headRef, h) == NULL);
assert(countNodes(headRef) == (4 - h));
h++;
}
}
/*// sort
void test6()
{
struct node *headRef=NULL;
struct node *nptr = NULL;
int h=0;
int d[5] = {1, 0, -1, 5, 100};
int ds[5] = {-1, 0, 1, 5, 100};
while(h<5)
insertTail(&headRef,createNode(d[h++]));
sort(&headRef);
h = 0;
for (nptr = headRef; nptr != NULL; nptr = nptr->next, h++)
assert(nptr->item == ds[h]);
}*/
int main( int argc, char ** argv )
{
int testNum = 0;
if ( argc < 2 ) {
fprintf(stderr, "\n usage: %s test-num\n", argv[0]);
return 1;
}
testNum = atoi(argv[1]);
switch(testNum){
case 1:
test1();
break;
case 2:
test2();
break;
case 3:
test3();
break;
case 4:
test4();
break;
case 5:
test5();
break;
case 6:
//test6();
break;
default:
fprintf(stderr, "\n usage: %s 1 .. 8\n", argv[0]);
return 1;
}
return 0;
}
我不知道這是否是錯誤,但是這一行幾乎可以肯定是錯誤的:
if(headRef = NULL) return 0; //if the head is NULL, return 0 (no nodes if no head)
並且應該是
if(headRef == NULL) return 0; //if the head is NULL, return 0 (no nodes if no head)
在countNodes()
。
這里有很多問題。
當您幾乎肯定不會分配新節點時,它們是在insertHead,insertTail,findNode和deleteNode中。 這些函數都不應該分配任何東西(除非您確實要復制調用者的節點,我對此表示懷疑,在這種情況下,您應該在insertHead和insertTail中進行分配,而不是在其他兩個中進行分配,並且應該使用自己的createNode函數來執行此操作)。 通常,我希望insertHead函數例如僅采用傳入的節點並將其插入列表的開頭。 它通常不會分配新節點並復制傳入節點的內容。
insertTail函數需要一些工作。 每次它都會泄漏一個節點,並且我認為,如果將其追加到一個空列表(新尾也是新頭的情況),它就會崩潰。 嘗試類似:
void insertTail(struct node **head, struct node *n)
{
struct node **tmp = head;
while (*tmp != NULL)
{
tmp = &((*tmp)->next);
}
*tmp = n;
n->next = NULL;
}
在countNodes中,您具有if(headRef = NULL),但應為==,而不是=。
沒有測試分配失敗(盡管這不太可能是導致段錯誤的原因)。
就個人而言,我將使用calloc而不是malloc,以便新節點的內容為零。
如果您對deleteNode的調用返回NULL,則deleteNode函數將進行seqfault。
我建議添加一些斷言,例如:
void insertHead(struct node **head, struct node *n)
{
assert(head != NULL);
assert(n != NULL);
assert(n->next == NULL);
n->next = *head;
*head = n;
}
我建議添加一些調試工具,例如:
void printNodes(struct node *head)
{
int count = 0;
while (head != NULL)
{
printf("Item[%d] at %p = %d\n", ++count, head, head->item);
head = head->next;
}
}
struct node* tmp = malloc(sizeof(struct node));
在使用過此功能的任何地方創建一個錯誤,根據ANSI規范的malloc返回指向分配地址的指針,並且您必須手動將其類型轉換為所需的類型,正確的語法是
struct node* tmp = (struct node*)malloc(sizeof(struct node));
你也在這樣做
*tmp = *head;
您必須分配指針,而不是分配相應內存位置中包含的實際值,因此請寫tmp=head
因為根據標准,* p表示指針所指向的位置的值
同樣糟糕的編程風格,您要在每個函數中分配內存,可以在主函數中創建一個指針並僅分配一次內存,然后在函數中使用它
一個關於細分錯誤的不錯的技巧教程在這里
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.