Domanda

Devo ammettere che sono un neofita della C, ma questo mi ha lasciato perplesso. Sto lavorando all'implementazione di un elenco collegato per esercitarmi e sto ottenendo un segfault semplicemente aggiungendo una variabile alla funzione 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;
}

Questo codice viene compilato (gcc -Wall -o list list.c) e funziona bene:

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

Ma se decomprimo int foo alla fine di split_node , compilo ed eseguo, ottengo:

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

gdb mi dà questo backtrace:

#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

Perché l'aggiunta di una definizione variabile causerebbe un segfault? Sembra che stia distruggendo il puntatore del contenuto del nodo appena creato. Non ho capito bene; qualche aiuto?

È stato utile?

Soluzione

Devi allocare dinamicamente i tuoi nodi (usando malloc).

Come hai, il tuo nuovo nodo è dichiarato in pila. Quando la funzione split ritorna, quel nuovo nodo non è più memoria valida.

L'aggiunta di una variabile provoca un segfault perché quella variabile modifica il layout dello stack causando un comportamento leggermente diverso al ritorno della funzione.

Altri suggerimenti

Prova a impostare la proprietà figlio di Nodi su NULL, C non azzera automaticamente la memoria, quindi sembra che potresti avere spazzatura in figlio (o potresti usare calloc invece di malloc). Anche la risposta di SoapBox è corretta.

Valgrind è un ottimo strumento per aiutarti a trovare questo tipo di problemi. Puoi semplicemente fare " valgrind myappname " dalla riga di comando e ti fornirà i dettagli su questi tipi di errori.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top