簡體   English   中英

Mergesort 實現中的分段錯誤

[英]Segmentation Fault in Mergesort implementation

我有一個程序 Mergesort 與一個無序列表一起工作。我得到的問題是 Segmentation Fault (core dumped)。

實際上,我經常收到此錯誤,但我不知道如何解決。 此外,它不會顯示任何錯誤或警告消息來查找它。 在這個源代碼和其他一般情況下,我真的需要知道為什么我有這個以及我如何修復它。

#include <stdio.h>
#include <stdlib.h>

typedef struct node_t node;
typedef struct node_t { int key; node *next; } node;
static node *head, *z;
node *merge(node *a, node *b)
{
    z->next =z;
    node *c = z;
    do
    {
        if (a->key > b->key)
        {
            c->next = a; c = a; a = a->next;
        }
        else
        {
            c->next = b; c = b; b = b->next;
        }
    } while (c != z);
    c = z->next;
    z->next = NULL;
    return c;
}
node *mergesort(node *c) {
    node *a = NULL; 
    node *b = NULL;
    if (c != NULL && c->next->next != NULL) {
        a = c; b = c;
        while (b->next != NULL && b->next->next != NULL) {
            c = c->next;
            b = b->next->next;
        }
        b = c->next;
        c->next = NULL;
        return merge(mergesort(a), mergesort(b));
    }
    return c;
}
void printList(node* node) 
{ 
    while (node != NULL) { 
        printf("%d ", node->key); 
        node = node->next; 
    } 
} 
node *listcreate(int n, node *a)
{
    node *head = NULL;
    node *temp = NULL;
    node *p = NULL;
    int i=0;
    while(i<n)
    {
        temp = (node*) malloc(sizeof(node*));
        printf("Please insert the number: ");
        scanf("%d", &(temp->key));
        temp->next = NULL;
        if(head == NULL)
        head = temp;
        else
        {
            p = head;
            while(p->next != NULL)
            p = p->next;
            p->next = temp;
        }
        i++;
    }
    a = head;
}
int main() 
{ 
    node *a = NULL;
    listcreate(3, a);
    a = mergesort(a);
    printf("Sorted Linked List is: \n"); 
    printList(a); 

    getchar(); 
    return 0; 
} 

首先,在包含stdlib.h調用您的函數mergesort是不正確的,並且應該會在最近的 C 編譯器中引發錯誤。

接下來,此代碼序列通過取消引用空指針來調用未定義行為:

node *z = NULL;
node *c = z;
c->next = a;  //  UB!

此時, cNULL,因此您不應使用c->next 使用常見的 C 實現嘗試寫入導致 seg 錯誤的不允許的內存。


您的算法嘗試使用sentinel ,但恕我直言,這不是一個合適的用例。 只記住第一個值更簡單。 並且您還應該處理到達兩個排序列表之一末尾的情況。 代碼可以變成:

node *merge(node *a, node *b)
{
    node *c = z;           // current node initialized to null
    node *top;             // declare the future return value
    do
    {
        if (a->key > b->key)
        {
            if (c == z) top = a;    // if first value, remember it
            else c->next = a;       // else add the node to current list
            c = a; a = a->next;
            if (a == NULL) {        // explicitely handle end of input list
                c->next = b;
                break;
            }
        }
        else
        {
            if (c == z) top = b;
            else c->next = b; 
            c = b; b = b->next;
            if (b == NULL) {
                c->next = a;
            break;
            }
        }
    } while (c != z);
    return top;
}

但這還不是全部。 您的代碼是 C 和 C++ 的混合體。 您只使用 C 庫函數,但使用 C++ 編譯器編譯代碼。 C 語言不允許函數重載,因此您不應重復使用具有不同參數集 ( mergesort ) 的標准庫函數的名稱。 而在 C 語言中,您不需要強制轉換 malloc

即使使用我的修復,如果您不更改mergesort函數的名稱,您的代碼也會在任何體面的C編譯器上mergesort 你被警告了。

對於最后一個問題,我認為分段錯誤的主要原因是訪問未初始化、超出程序范圍或嘗試修改字符串文字的內存。 這些可能會導致分段錯誤,但不能保證它們會導致分段錯誤。 以下是分段錯誤的一些常見原因 -

訪問數組越界

取消引用 NULL 指針

取消引用已釋放的內存

取消引用未初始化的指針

“&”(地址)和“*”(取消引用)運算符的錯誤使用

printf 和 scanf 語句中的格式說明符不正確

堆棧溢出

寫入只讀存儲器

暫無
暫無

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

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