Mergesort 实现中的分段错误

Segmentation Fault in Mergesort implementation

我有一个程序 Mergesort 可以处理无序链接 list.The 我遇到的问题是分段错误(核心已转储)。

实际上我经常遇到这个错误,但我不知道如何解决。此外,它不会显示任何错误或警告消息来查找它。在这个源代码和其他一般情况下,我真的需要知道为什么我有这个以及我如何修复它。

#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; 
} 

对于最后一个问题,我认为分段错误的主要原因是访问未初始化的内存、程序越界或试图修改字符串文字。这些可能会导致分段错误,但不能保证它们会导致分段错误。以下是分段错误的一些常见原因 -

越界访问数组

取消引用 NULL 指针

取消引用释放的内存

取消引用未初始化的指针

“&”(地址)和“*”(解引用)运算符使用不当

printf 和 scanf 语句中的格式说明符不正确

堆栈溢出

写入只读存储器

首先,在包含 stdlib.h 的同时调用您的函数 mergesort 是不正确的,应该会在最近的 C 编译器中引发错误。

接下来,此代码序列通过取消引用空指针来调用未定义行为:

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

此时,cNULL,所以你不应该使用c->next。使用常见的 C 实现尝试写入导致段错误的不允许的内存。


您的算法尝试使用 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语言中,you need not cast malloc.

即使使用我的修复程序,如果您不更改 mergesort 函数的名称,您的代码也会在任何体面的 C 编译器上中断。您已收到警告。