【问题标题】:C programming segmentation fault linked list programC编程分段错误链表程序
【发布时间】:2013-04-05 01:41:47
【问题描述】:

我对 c(和这个站点)还很陌生,我遇到了很多分段错误的问题。我正在编写一个程序,它创建一个数字链表并按升序插入值。

     void insert(struct element **head, struct element *new){   
            if((*head)->next == NULL && (*new).i > (*(*head)->next).i){
                (*head)->next = new;
                return;     
            }
            if((*head)->next == NULL && (*new).i < (*(*head)->next).i){
                new->next = (*head)->next;
                *head = new;    
                return;
            }
            struct element *prev = *head;
            struct element *current = (*head)->next;
            while(current->next != NULL){
                if((*new).i < (*current).i){
                    prev = current;
                    current = current->next;
                } else if((*new).i > (*current).i){
                    new->next = current;
                    prev->next = new;
                }
            }
        }
        int main (void){
            struct element **head;
            int value;
            printf("%s", "TEST" );
            printf("%s" , "Please type in an integer value. ");
            scanf("%d" , &value);
            printf("%s", "TEST" );
            do{
                printf("%s", "TEST" );
                struct element *new;
                if((new = malloc(sizeof(struct element))) == NULL){
                return(NULL);
                }
                printf("%s", "TEST" );
                (*new).i = value;
                printf("%s", "TEST" );
                if(head == NULL){
                    *head = new;
                    printList(*head);
                }  else if(value <= 0){
                    printListBackwards(*head);
                }   
                else {

                    insert(head, new);
                    printList(*head);
                }
                } while(value > 0);

我不需要关于插入或其他任何逻辑是否正确的帮助。我什至没有机会真正测试它,因为在提示符后输入整数后,我立即遇到分段错误。我知道这看起来很时髦,但是规范要求您使用指向结构的指针(链表的头部)的指针。

【问题讨论】:

  • 共享代码时,请确保其他用户可以快速编译您的代码并重现错误。您的代码在 main 函数中缺少结构定义、函数甚至右括号。此外,在寻求帮助之前,请确保您的代码在编译时不显示警告/错误。尝试使用标志-Wall -Wextra 进行编译。在找出段错误时,我发现valgrind 是一个非常有用的工具,试一试。只需记住使用-g 标志进行编译以生成调试符号

标签: c pointers linked-list segmentation-fault


【解决方案1】:

您确定要让 head 成为 element** 而不是 element*?这种额外的分离程度会给您带来问题,其中最重要的是难以阅读的代码。

这是让我大吃一惊的主要事情:

if(head == NULL){
    *head = new;
    printList(*head);
}

您确认 head 是一个 NULL 指针,然后立即尝试使用 * 取消引用它。如果你真的坚持 head 是一个双指针,那么你需要在取消引用之前动态分配它。像这样:

if(head == NULL){
    head = malloc(sizeof(element*));
    *head = new;
    printList(*head);
}

这实际上可能在语法上并不完美(我来自 C++),但你明白了。不过,说到 C++,在 C 中将变量命名为“new”通常被认为是不好的做法,因为 new 是 C++ 中的关键字。

【讨论】:

  • 谢谢。我将 head 更改为单个指针,看看它是否工作得更好。我仍然不确定为什么当我运行程序时,它在失败之前没有从 main 打印出第二个“TEST”行。
  • @user2247284 您的 printf 字符串不以换行符结尾,因此它们不会被刷新。另外,通常只做printf("TEST\n");
  • 为了扩展 Jim 所说的, printf 实际上不会立即打印,除非它必须这样做。在您的程序中,它将“TEST”放入缓冲区,但由于尚未到达换行符,因此决定等待。然后你的程序在刷新缓冲区之前就崩溃了。
【解决方案2】:
struct element **head;

你不想这样。相反,

struct element *head = NULL;

然后,当你调用 insert 时,使用

insert(&head, new);

您还有许多其他错误和糟糕的用法,但这是您特定问题的开始。

【讨论】:

    【解决方案3】:

    您帖子的第二行出现了段错误

    if((*head)->next == NULL && (*new).i > (*(*head)->next).i){
        (*head)->next = new;
        return;     
    }
    

    分段错误意味着您正在尝试访问不允许访问的内存。例如,您不能取消引用 NULL 指针。

    您的if 语句是这样评估的。 检查(*head)-&gt;next 是否为空。

    如果不为NULL,则跳过其余部分。

    如果它为 NULL,那么您可以用 NULL 替换后面的每个 (*head)-&gt;next。这意味着下面的部分&amp;&amp; (*new).i &gt; (*(*head)-&gt;next.i)可以改写成如下&amp;&amp; (*new).i &gt; ((*NULL).i)...

    简而言之,您正在尝试取消引用 NULL 指针值。

    另请参阅@Parker Kemp 的帖子。有很多次你正确地检查了 NULL 但误解了它的含义。

    我可以为你重写代码,但我认为你会从像 this onethis one 这样的教程中受益更多

    我强烈建议您绘制数据结构图并为指针绘制箭头。

    【讨论】:

    • 好的,谢谢。你能告诉我为什么当我运行程序时,它甚至在尝试调用函数插入之前就无法输出第二个“TEST”行吗?在 C 中检查 NULL 的安全方法是什么?
    • 您正确地测试了 NULL,但您没有使用正确的比较。 if (pointer == NULL) ... 会告诉你指针是否包含一个 NULL 值,这意味着它指向被禁止的内存。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    相关资源
    最近更新 更多