列表插入中 strcmp 的分段错误
Segmentation fault with strcmp in a list insertion
我正在尝试按字母顺序创建列表(首先按作者,然后按姓名)。我试图通过将两个字符串与 strcmp()
进行比较来做到这一点,但我遇到了分段错误。
我将把 GDB 运行 结果和函数留在下面,它是我用列表制作的第一个程序之一,所以代码可能还有其他错误。
GDB 运行 :
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400c65 in insert (lPtr=0x7fffffffeb38, isbn_i=978044,
name_i=0x7fffffffeb40 "Suzanne Collins",
author_i=0x7fffffffeb80 "The Hunger Games") at main.c:178
178 while(strcmp(author_i, currPtr->author) < 0){
typedef struct library{ //struct insertion from stdin
int isbn;
char *author;
char *name;
int act; //actual books in memory
int tot; //total books
struct library *nextPtr; //node
}Lib;
typedef Lib *NodePtr;
//called by a while, receives input from integers and two arrays of char
void insert(NodePtr *lPtr, int isbn_i, char *name_i, char *author_i){
NodePtr newPtr = malloc(sizeof(Lib));
newPtr->isbn = isbn_i; //scanf insertion in node
newPtr->author = author_i;
newPtr->name = name_i;
newPtr->nextPtr = NULL;
NodePtr prevPtr = NULL;
newPtr->act = 1;
newPtr->tot = 1;
if(lPtr == NULL){ //empty list
*lPtr = newPtr;
return;
}
NodePtr currPtr = *lPtr;
while(strcmp(author_i, currPtr->author) < 0){ //author is different, list slides
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
}
if(strcmp(author_i, currPtr->author)== 0){ //same author
while(strcmp(name_i, currPtr->name) < 0){ //list sliding
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
}
if(strcmp(name_i, currPtr->name) == 0){
currPtr->act += 1; //updates current counter and returns (to avoid duplicates)
currPtr->tot += 1;
free(newPtr);
return;
}
}
prevPtr->nextPtr = newPtr; //insertion between two nodes
newPtr->nextPtr = currPtr;
}
在以下代码中:
while(strcmp(author_i, currPtr->author) < 0){ //author is different, list slides
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
}
您不检查 currPtr->nextPtr
是否为 NULL
(在您的列表末尾),
如果您的列表作者仅包含应在之后 author_i
排序的作者,您将到达结尾而找不到插入的地方。
示例(为简洁起见省略了不相关的字段):
currPtr = {author:"Cressida Cowell", nextPtr=NULL};
insert(lPtr = &currPtr, ...,author_i = "Suzanne Collins", ...);
/// insertion location loop
// while loop unrolled
if("Suzanne Collins" > "Cressida Cowell") {
prevPtr = currPtr ; // prevPtr = {author:"Cressida Cowell", nextPtr=NULL};
currPtr = currPtr->nextPtr; // currPtr = NULL
}
// next iteration
if("Suzanne Collins"> NULL->author ) // de-referencing a NULL pointer, causing a Segmentation fault
您可以使用以下修复方法部分修复代码:
while(strcmp(author_i, currPtr->author) < 0){ //author is different, list slides
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
if(currPtr == NULL) {break;} // exit loop if at end of the list
}
你仍然需要处理currPtr == NULL
以避免de-referencing在检查标题时currPtr
中的NULL指针,我的建议是结合插入位置搜索循环中的条件.
// implement a node comparison function
int compareLib(NodePtr lib1, NodePtr lib2) {
if((lib1 == NULL)||(lib2 == NULL)) return 0;
int author_compare = strcmp(lib1->author, lib2->author);
if (author_compare != 0) return author_compare;
return strcmp(lib1->name, lib2->name);
}
...
while(compareLib(newPtr, currPtr)){
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
if(currPtr == NULL) {break;} // exit loop if at end of the list
}
添加新列表节点时还需要处理currPtr == NULL
我正在尝试按字母顺序创建列表(首先按作者,然后按姓名)。我试图通过将两个字符串与 strcmp()
进行比较来做到这一点,但我遇到了分段错误。
我将把 GDB 运行 结果和函数留在下面,它是我用列表制作的第一个程序之一,所以代码可能还有其他错误。
GDB 运行 :
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400c65 in insert (lPtr=0x7fffffffeb38, isbn_i=978044,
name_i=0x7fffffffeb40 "Suzanne Collins",
author_i=0x7fffffffeb80 "The Hunger Games") at main.c:178
178 while(strcmp(author_i, currPtr->author) < 0){
typedef struct library{ //struct insertion from stdin
int isbn;
char *author;
char *name;
int act; //actual books in memory
int tot; //total books
struct library *nextPtr; //node
}Lib;
typedef Lib *NodePtr;
//called by a while, receives input from integers and two arrays of char
void insert(NodePtr *lPtr, int isbn_i, char *name_i, char *author_i){
NodePtr newPtr = malloc(sizeof(Lib));
newPtr->isbn = isbn_i; //scanf insertion in node
newPtr->author = author_i;
newPtr->name = name_i;
newPtr->nextPtr = NULL;
NodePtr prevPtr = NULL;
newPtr->act = 1;
newPtr->tot = 1;
if(lPtr == NULL){ //empty list
*lPtr = newPtr;
return;
}
NodePtr currPtr = *lPtr;
while(strcmp(author_i, currPtr->author) < 0){ //author is different, list slides
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
}
if(strcmp(author_i, currPtr->author)== 0){ //same author
while(strcmp(name_i, currPtr->name) < 0){ //list sliding
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
}
if(strcmp(name_i, currPtr->name) == 0){
currPtr->act += 1; //updates current counter and returns (to avoid duplicates)
currPtr->tot += 1;
free(newPtr);
return;
}
}
prevPtr->nextPtr = newPtr; //insertion between two nodes
newPtr->nextPtr = currPtr;
}
在以下代码中:
while(strcmp(author_i, currPtr->author) < 0){ //author is different, list slides
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
}
您不检查 currPtr->nextPtr
是否为 NULL
(在您的列表末尾),
如果您的列表作者仅包含应在之后 author_i
排序的作者,您将到达结尾而找不到插入的地方。
示例(为简洁起见省略了不相关的字段):
currPtr = {author:"Cressida Cowell", nextPtr=NULL};
insert(lPtr = &currPtr, ...,author_i = "Suzanne Collins", ...);
/// insertion location loop
// while loop unrolled
if("Suzanne Collins" > "Cressida Cowell") {
prevPtr = currPtr ; // prevPtr = {author:"Cressida Cowell", nextPtr=NULL};
currPtr = currPtr->nextPtr; // currPtr = NULL
}
// next iteration
if("Suzanne Collins"> NULL->author ) // de-referencing a NULL pointer, causing a Segmentation fault
您可以使用以下修复方法部分修复代码:
while(strcmp(author_i, currPtr->author) < 0){ //author is different, list slides
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
if(currPtr == NULL) {break;} // exit loop if at end of the list
}
你仍然需要处理currPtr == NULL
以避免de-referencing在检查标题时currPtr
中的NULL指针,我的建议是结合插入位置搜索循环中的条件.
// implement a node comparison function
int compareLib(NodePtr lib1, NodePtr lib2) {
if((lib1 == NULL)||(lib2 == NULL)) return 0;
int author_compare = strcmp(lib1->author, lib2->author);
if (author_compare != 0) return author_compare;
return strcmp(lib1->name, lib2->name);
}
...
while(compareLib(newPtr, currPtr)){
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
if(currPtr == NULL) {break;} // exit loop if at end of the list
}
添加新列表节点时还需要处理currPtr == NULL