Segfault от добавления переменной

Я, по общему признанию, новичок в C, но это поставило меня в тупик. Я работаю над реализацией связанного списка для практики, и я получаю segfault, просто добавляя переменную в функцию 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

Но если я раскомментирую int foo в конце split_node, скомпилирую и запущу, я получу:

$ ./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

Почему добавление определения переменной может привести к segfault? Похоже, он разбивает указатель содержимого вновь созданного узла. Я запутался; любая помощь?


person kevingessner    schedule 11.01.2009    source источник


Ответы (3)


Вам нужно динамически распределять свои узлы (используя malloc).

Как только вы это сделаете, ваш новый узел будет объявлен в стеке. Когда функция разделения возвращается, этот новый узел больше не является действительной памятью.

Добавление переменной вызывает segfault, потому что эта переменная изменяет макет стека, что приводит к немного другому поведению при возврате функции.

person SoapBox    schedule 11.01.2009

Попробуйте установить для дочернего свойства Nodes значение NULL, C автоматически не обнуляет память, поэтому похоже, что у вас может быть мусор в дочернем элементе (или вы можете использовать calloc вместо malloc). Ответ SoapBox также правильный.

person Kevin Loney    schedule 11.01.2009

Valgrind — отличный инструмент для поиска подобных проблем. Вы можете просто сделать «valgrind myappname» из командной строки, и она предоставит вам подробную информацию об этих типах ошибок.

person Paul Vincent Craven    schedule 11.01.2009