修复加载 'Node *' 类型的空指针错误
Fixing load of null pointer of type 'Node *' error
我正在用 C 语言实现链表数据结构。下面是我的链表实现文件的当前函数 (llist.c)
#include "llist.h"
// Frees all allocated memory associated with the list pointers iteratively
void deleteList(Node **list) {
Node* ptr = *list;
Node* temp;
while(ptr != NULL) {
free(ptr->data);
temp = ptr;
ptr=ptr->next;
free(temp);
}
}
// Frees all allocated memory associated with a single node
void deleteNode(Node **toDelete) {
Node * del = *toDelete;
free(del->data);
free(del);
}
// Allocates memory for a new string and returns a pointer to the memory
Node *newNode(char *string) {
unsigned long len = strlen(string);
printf("length : %lu \n\n", len);
Node *temp = (Node*)malloc(sizeof(Node));
temp->data = (char*)malloc(len + 1*sizeof(char));
strcpy(temp->data, string);
temp->next = NULL;
return temp;
}
// Removes a node from the front of a list
Node *pop(Node **list) {
Node *newptr = (*list)->next;
deleteNode(list);
return newptr;
}
// Adds a node to the front of a list
void push(Node **list, Node *toAdd) {
toAdd->next = *list;
*list = toAdd;
}
// Return a list of pointers in order
void reverseOrder(Node **list) {
Node* prev = NULL;
Node* current = *list;
Node* next;
while (current != NULL) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*list = prev;
}
// Prints the string stored in a single node
void printNode(Node *singleNode) {
printf("Data : %s", singleNode->data);
}
// Prints an entire linked list. Nodes are printed from first to last
void printLinkedList(Node *linkedList) {
Node *temp = linkedList;
while(temp!=NULL) {
printf("Data : %s", temp->data);
temp = temp->next;
}
}
在我的驱动程序文件中测试实现时,我收到以下错误
runtime error: load of null pointer of type 'Node *' (aka 'struct listNode *')
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior llist.c:49:19
其中第 49 行对应于 llist.c 文件中的 toAdd->next = *list
我正在努力弄清楚为什么会出现此错误,因为我正在使用适当的参数调用推送函数到最初为空 (NULL) 的链表。
驱动文件(测试llist.c)供参考:
#include "llist.h"
int main (int argc, char *argv[]) {
printf("argc: %d", argc);
printf("\n\n");
int num_inputs = argc;
Node **list = NULL;
if (argc == 1) {
printf("No arguments passed.\n");
} else {
for (int i = 1; i < num_inputs; i++) {
printf("String is: %s\n", argv[i]);
Node *n = newNode(argv[i]);
printf("String is : %s\n\n", argv[i]);
push(list, n);
printLinkedList(*list);
}
reverseOrder(list);
pop(list);
deleteList(list);
}
return 0;
}
头文件(llist.h),其中定义了节点数据类型和函数
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// The listNode data type for storing entries in a linked list
typedef struct listNode Node;
struct listNode {
char *data;
Node *next;
};
// Frees all allocated memory associated with the list pointers iteratively
void deleteList(Node **list);
// Frees all allocated memory associated with a single node
void deleteNode(Node **toDelete);
// Allocates memory for a new string and returns a pointer to the memory
Node *newNode(char *string);
// Removes a node from the front of a list and returns a pointer to said node
Node *pop(Node **list);
// Adds a node to the front of a list
void push(Node **list, Node *toAdd);
// Return a list of pointers in order
void reverseOrder(Node **list);
// Prints the string stored in a single node
void printNode(Node *singleNode);
// Prints an entire linked list. Nodes are printed from first to last
void printLinkedList(Node *linkedList);
当您将指针列表初始化为空指针时
Node **list = NULL;
然后在函数中 push
你不能取消引用这个指针
void push(Node **list, Node *toAdd) {
toAdd->next = *list;
*list = toAdd;
}
并且错误消息报告了这个问题。
你应该像这样声明指针
Node *list = NULL;
并将其传递给需要 Node **
类型对象的函数,例如
push( &list, n );
如果函数像这样声明就更好了
int push( Node **list, const char * );
也就是说,它应该报告一个新节点是否被成功推送,并且新节点的分配应该对调用该函数的用户隐藏。
请注意,例如函数 deleteNode
没有多大意义。
void deleteList(Node **list) {
Node* ptr = *list;
Node* temp;
while(ptr != NULL) {
free(ptr->data);
temp = ptr;
ptr=ptr->next;
free(temp);
}
}
指向列表头节点的指针通过引用传递。但是在函数内它的值没有改变。因此在退出函数后指向头节点的指针仍将具有其原始值。
函数可以这样定义
void deleteList( Node **list )
{
while ( *list != NULL )
{
Node *ptr = *list;
*list = ( *list )->next;
free( ptr->data );
free( ptr );
}
}
函数pop
不检查传递给链表头节点的指针是否等于NULL
Node *pop(Node **list) {
Node *newptr = (*list)->next;
deleteNode(list);
return newptr;
}
它还returns指向列表中成为当前头节点的下一个节点的指针。但是返回的指针并没有在main
中使用
pop(list);
注意表达式1 * sizeof( char )
在这个声明中用作初始值设定项的表达式中没有意义
temp->data = (char*)malloc(len + 1*sizeof(char));
要么写
temp->data = (char*)malloc(len + 1);
或喜欢
temp->data = (char*)malloc( ( len + 1 )*sizeof(char));
我正在用 C 语言实现链表数据结构。下面是我的链表实现文件的当前函数 (llist.c)
#include "llist.h"
// Frees all allocated memory associated with the list pointers iteratively
void deleteList(Node **list) {
Node* ptr = *list;
Node* temp;
while(ptr != NULL) {
free(ptr->data);
temp = ptr;
ptr=ptr->next;
free(temp);
}
}
// Frees all allocated memory associated with a single node
void deleteNode(Node **toDelete) {
Node * del = *toDelete;
free(del->data);
free(del);
}
// Allocates memory for a new string and returns a pointer to the memory
Node *newNode(char *string) {
unsigned long len = strlen(string);
printf("length : %lu \n\n", len);
Node *temp = (Node*)malloc(sizeof(Node));
temp->data = (char*)malloc(len + 1*sizeof(char));
strcpy(temp->data, string);
temp->next = NULL;
return temp;
}
// Removes a node from the front of a list
Node *pop(Node **list) {
Node *newptr = (*list)->next;
deleteNode(list);
return newptr;
}
// Adds a node to the front of a list
void push(Node **list, Node *toAdd) {
toAdd->next = *list;
*list = toAdd;
}
// Return a list of pointers in order
void reverseOrder(Node **list) {
Node* prev = NULL;
Node* current = *list;
Node* next;
while (current != NULL) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*list = prev;
}
// Prints the string stored in a single node
void printNode(Node *singleNode) {
printf("Data : %s", singleNode->data);
}
// Prints an entire linked list. Nodes are printed from first to last
void printLinkedList(Node *linkedList) {
Node *temp = linkedList;
while(temp!=NULL) {
printf("Data : %s", temp->data);
temp = temp->next;
}
}
在我的驱动程序文件中测试实现时,我收到以下错误
runtime error: load of null pointer of type 'Node *' (aka 'struct listNode *') SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior llist.c:49:19
其中第 49 行对应于 llist.c 文件中的 toAdd->next = *list
我正在努力弄清楚为什么会出现此错误,因为我正在使用适当的参数调用推送函数到最初为空 (NULL) 的链表。
驱动文件(测试llist.c)供参考:
#include "llist.h"
int main (int argc, char *argv[]) {
printf("argc: %d", argc);
printf("\n\n");
int num_inputs = argc;
Node **list = NULL;
if (argc == 1) {
printf("No arguments passed.\n");
} else {
for (int i = 1; i < num_inputs; i++) {
printf("String is: %s\n", argv[i]);
Node *n = newNode(argv[i]);
printf("String is : %s\n\n", argv[i]);
push(list, n);
printLinkedList(*list);
}
reverseOrder(list);
pop(list);
deleteList(list);
}
return 0;
}
头文件(llist.h),其中定义了节点数据类型和函数
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// The listNode data type for storing entries in a linked list
typedef struct listNode Node;
struct listNode {
char *data;
Node *next;
};
// Frees all allocated memory associated with the list pointers iteratively
void deleteList(Node **list);
// Frees all allocated memory associated with a single node
void deleteNode(Node **toDelete);
// Allocates memory for a new string and returns a pointer to the memory
Node *newNode(char *string);
// Removes a node from the front of a list and returns a pointer to said node
Node *pop(Node **list);
// Adds a node to the front of a list
void push(Node **list, Node *toAdd);
// Return a list of pointers in order
void reverseOrder(Node **list);
// Prints the string stored in a single node
void printNode(Node *singleNode);
// Prints an entire linked list. Nodes are printed from first to last
void printLinkedList(Node *linkedList);
当您将指针列表初始化为空指针时
Node **list = NULL;
然后在函数中 push
你不能取消引用这个指针
void push(Node **list, Node *toAdd) {
toAdd->next = *list;
*list = toAdd;
}
并且错误消息报告了这个问题。
你应该像这样声明指针
Node *list = NULL;
并将其传递给需要 Node **
类型对象的函数,例如
push( &list, n );
如果函数像这样声明就更好了
int push( Node **list, const char * );
也就是说,它应该报告一个新节点是否被成功推送,并且新节点的分配应该对调用该函数的用户隐藏。
请注意,例如函数 deleteNode
没有多大意义。
void deleteList(Node **list) {
Node* ptr = *list;
Node* temp;
while(ptr != NULL) {
free(ptr->data);
temp = ptr;
ptr=ptr->next;
free(temp);
}
}
指向列表头节点的指针通过引用传递。但是在函数内它的值没有改变。因此在退出函数后指向头节点的指针仍将具有其原始值。
函数可以这样定义
void deleteList( Node **list )
{
while ( *list != NULL )
{
Node *ptr = *list;
*list = ( *list )->next;
free( ptr->data );
free( ptr );
}
}
函数pop
不检查传递给链表头节点的指针是否等于NULL
Node *pop(Node **list) {
Node *newptr = (*list)->next;
deleteNode(list);
return newptr;
}
它还returns指向列表中成为当前头节点的下一个节点的指针。但是返回的指针并没有在main
中使用pop(list);
注意表达式1 * sizeof( char )
在这个声明中用作初始值设定项的表达式中没有意义
temp->data = (char*)malloc(len + 1*sizeof(char));
要么写
temp->data = (char*)malloc(len + 1);
或喜欢
temp->data = (char*)malloc( ( len + 1 )*sizeof(char));