【问题标题】:Why am I getting Segmentation fault?为什么我得到分段错误?
【发布时间】:2013-05-16 17:38:26
【问题描述】:

我正在尝试学习如何在 C 中使用结构和链表,但我真的不明白为什么下面的代码会给我分段错误:

我有 3 个文件,分别名为 list.h、operations.c 和 main.c。在文件list.h中:

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

typedef char DATA;

struct linked_list {
    DATA                   d;
    struct linked_list *next;
};

typedef struct linked_list ELEMENT;
typedef ELEMENT              *LINK;

LINK string_to_list(char s[]);
void print_list(LINK);

文件operations.c

#include "list.h"

LINK string_to_list(char s[]){
    LINK head = NULL;

    if (s[0]) {
        ELEMENT c = {s[0], NULL};
        c.next = string_to_list(s+1);
        head = &c;
    }

    return head;
}

void print_list(LINK head) {
    if(head != NULL){
        putchar(head -> d);
        print_list(head -> next);
    } else {
        putchar('\n');
    }
}

文件main.c

#include "list.h"

int main(void) {
    LINK head = string_to_list("wtf");
    print_list(head);
    return 0;
}

【问题讨论】:

  • 从不返回对本地存储的引用。
  • 就目前而言,如果没有一些动态内存分配或一些花哨的池工作,您将无法在列表中拥有超过 1 个元素。
  • @CaptainSkyhawk:实际上他有,但时间不长。

标签: c segmentation-fault undefined-behavior


【解决方案1】:
if (s[0]) {
    ELEMENT c = {s[0], NULL};        // Allocate space for struct on the stack
    c.next = string_to_list(s+1);
    head = &c;                       // Save the address to head
}  // <-- poof, c goes out of scope and is deallocated from the stack

return head; // <-- return address of deallocated object

【讨论】:

    【解决方案2】:
    if (s[0]) {
    --->    ELEMENT c = {s[0], NULL};
        c.next = string_to_list(s+1);
        head = &c;
    }
    
    return head;
    

    是本地内存。一旦您离开函数(甚至代码块),该内存就会被释放并且不再有效。你需要malloc()它,或者传入一些内存供这个函数使用,让它在这个函数之外存活。

    【讨论】:

      【解决方案3】:

      string_to_list 中,您在 if 语句中获取局部变量的地址(在大多数现代实现中,该地址存储在堆栈中):

      head = &c;
      

      然后在此处返回该地址:

      return head;
      

      变量cif语句结束后将不再存在,这是undefined behaviorC99 draft standard 部分 6.2.4 对象的存储持续时间 段落 2 说:

      [...]如果对象在其生命周期之外被引用,则行为未定义。[...]

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-06
        • 1970-01-01
        • 2018-09-22
        • 1970-01-01
        • 1970-01-01
        • 2014-05-23
        • 2020-08-03
        相关资源
        最近更新 更多