2

私は確かにストレート 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

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

変数定義を追加するとセグメンテーション違反が発生するのはなぜですか? 新しく作成されたノードのコンテンツ ポインタを壊しているようです。よくわかりません; 助けはありますか?

4

3 に答える 3

15

ノードを動的に割り当てる必要があります (malloc を使用)。

あなたが持っているように、あなたの新しいノードはスタック上で宣言されています。split 関数が戻ると、その新しいノードは有効なメモリではなくなります。

変数を追加すると、その変数がスタックのレイアウトを変更し、関数が戻るときにわずかに異なる動作を引き起こすため、segfault が発生します。

于 2009-01-11T21:08:07.280 に答える
0

Nodes 子プロパティを NULL に設定してみてください。C はメモリを自動的にゼロにしないため、子にガベージがあるように見えます (または、malloc の代わりに calloc を使用できます)。SoapBox の回答も正しいです。

于 2009-01-11T21:11:38.210 に答える