Pregunta

Ciertamente soy un novato en línea recta, pero esto me ha dejado perplejo. Estoy trabajando en una implementación de lista vinculada para la práctica, y obtengo un segfault simplemente agregando una variable a la función 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;
}

Este código compila (gcc -Wall -o list list.c) y funciona bien:

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

Pero si descomento int foo al final de split_node , compilo y ejecuto, obtengo:

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

gdb me da esta traza inversa:

#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

¿Por qué agregar una definición de variable causaría una segfault? Parece estar rompiendo el puntero de contenido del nodo recién creado. Estoy confundido; alguna ayuda?

¿Fue útil?

Solución

Necesita asignar dinámicamente sus nodos (usando malloc).

Como lo tiene, su nuevo nodo se declara en la pila. Cuando vuelve la función dividida, ese nuevo nodo ya no es memoria válida.

Agregar una variable causa una falla predeterminada porque esa variable cambia el diseño de la pila y causa un comportamiento ligeramente diferente cuando la función regresa.

Otros consejos

Intente establecer la propiedad secundaria Nodes en NULL, C no pone en cero automáticamente la memoria, por lo que parece que puede tener basura en el elemento secundario (o podría usar calloc en lugar de malloc). La respuesta de SoapBox también es correcta.

Valgrind es una gran herramienta para ayudar a encontrar este tipo de problemas. Simplemente puede hacer '' valgrind myappname '' desde la línea de comandos y le dará detalles sobre este tipo de errores.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top