【问题标题】:Segfault from adding a variable添加变量的段错误
【发布时间】:2010-09-30 19:51:18
【问题描述】:

诚然,我是一个纯 C 的新手,但这让我很困惑。我正在研究一个链表实现以供练习,我只是通过向 split_node 函数添加一个变量来得到一个段错误:

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

struct Node {
    struct Node *child;
    char *content;
};

void print_list(struct Node node);
void split_node(struct Node *node, int position);

int main() {

    struct Node head, second, third;

    head.content = "first";
    second.content = "second";
    third.content = "i'm third";

    head.child = &second;
    second.child = &third;

    print_list(head);
    split_node(&head, 3);
    print_list(head);

    return 0;
}

void print_list(struct Node node) {
    printf("%s\n", node.content);
    if(node.child) print_list(*node.child);
}

    /*
    Split node into two nodes, with the first position characters of the node's content remaining with node, and the remainder being copied to the new node. (It doesn't yet truncate the first node's string, but does do the copy.)
    */
void split_node(struct Node *node, int position) {
    if(position >= strlen((*node).content)) return;
    struct Node newNode;
    newNode.child = (*node).child;
    (*node).child = &newNode;

    int length = (strlen((*node).content) - position);
    newNode.content = malloc(sizeof(char) * (length + 1));
    strncpy(newNode.content, (*node).content + sizeof(char) * position, length);
    newNode.content[length] = '\0';

    //int foo;
}

此代码编译(gcc -Wall -o list list.c)并运行良好:

$ ./list
first
second
i'm third
first
st
second
i'm third

但是如果我在split_node 的末尾取消注释int foo,编译并运行,我得到:

$ ./list
first
second
i'm third
first
st
Segmentation fault

gdb 给了我这个回溯:

#0  0x91d6ae70 in strlen ()
#1  0x91dd3126 in puts ()
#2  0x00001f21 in print_list (node={child = 0xbcec815b, content = 0x8b000000 <Address 0x8b000000 out of bounds>}) at list.c:41
#3  0x00001f3c in print_list (node={child = 0x8fe0154b, content = 0x1ff6 "i'm third"}) at list.c:42
#4  0x00001f3c in print_list (node={child = 0xbffff568, content = 0x1fef "second"}) at list.c:42
#5  0x00001f3c in print_list (node={child = 0xbffff570, content = 0x1fe9 "first"}) at list.c:42
#6  0x00001ee0 in main () at list.c:33

为什么添加变量定义会导致段错误?它似乎正在破坏新创建节点的内容指针。我糊涂了;有什么帮助吗?

【问题讨论】:

    标签: c segmentation-fault


    【解决方案1】:

    您需要动态分配节点(使用 malloc)。

    正如你所拥有的,你的新节点被声明在堆栈上。当 split 函数返回时,该新节点不再是有效内存。

    添加变量会导致段错误,因为该变量会更改堆栈的布局,从而导致函数返回时的行为略有不同。

    【讨论】:

      【解决方案2】:

      尝试将 Nodes 子属性设置为 NULL,C 不会自动将内存归零,因此看起来您的子项中可能有垃圾(或者您可以使用 calloc 而不是 malloc)。 SoapBox 的回答也是正确的。

      【讨论】:

        【解决方案3】:

        Valgrind 是帮助查找此类问题的好工具。您可以从命令行执行“valgrind myappname”,它会为您提供有关这些类型错误的详细信息。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-03
          • 1970-01-01
          相关资源
          最近更新 更多