簡體   English   中英

列表插入中 strcmp 的分段錯誤

[英]Segmentation fault with strcmp in a list insertion

我正在嘗試按字母順序創建一個列表(首先按作者,然后按名稱)。 我試圖通過將兩個字符串與strcmp()進行比較來做到這一點,但我遇到了分段錯誤。

我將把 GDB 運行結果放在這里,而 function 是我用列表制作的第一個程序之一,因此代碼可能還有其他錯誤。

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以避免在檢查標題時取消引用 currPtr 中的currPtr指針,我的建議是結合插入位置搜索循環中的條件。

    // 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM