1

Cで構造体とリンク リストを使用する方法を学習しようとしていますが、次のコードでセグメンテーション エラーが発生する理由がよくわかりません。

list.h、operations.c、および main.cという名前の 3 つのファイルがあります。ファイルlist.h で:

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

typedef char DATA;

struct linked_list {
    DATA                   d;
    struct linked_list *next;
};

typedef struct linked_list ELEMENT;
typedef ELEMENT              *LINK;

LINK string_to_list(char s[]);
void print_list(LINK);

ファイルoperations.c :

#include "list.h"

LINK string_to_list(char s[]){
    LINK head = NULL;

    if (s[0]) {
        ELEMENT c = {s[0], NULL};
        c.next = string_to_list(s+1);
        head = &c;
    }

    return head;
}

void print_list(LINK head) {
    if(head != NULL){
        putchar(head -> d);
        print_list(head -> next);
    } else {
        putchar('\n');
    }
}

ファイルmain.c :

#include "list.h"

int main(void) {
    LINK head = string_to_list("wtf");
    print_list(head);
    return 0;
}
4

3 に答える 3

4
if (s[0]) {
    ELEMENT c = {s[0], NULL};        // Allocate space for struct on the stack
    c.next = string_to_list(s+1);
    head = &c;                       // Save the address to head
}  // <-- poof, c goes out of scope and is deallocated from the stack

return head; // <-- return address of deallocated object
于 2013-05-16T17:41:28.900 に答える
2
if (s[0]) {
--->    ELEMENT c = {s[0], NULL};
    c.next = string_to_list(s+1);
    head = &c;
}

return head;

ローカルメモリです。関数 (またはコード ブロック) を離れるとすぐに、そのメモリは解放され、有効ではなくなります。あなたはmalloc()それをする必要があります、またはこの関数がこの関数を超えて生きるために使用するために、この関数にいくつかのメモリを渡します。

于 2013-05-16T17:42:55.173 に答える
2

ifステートメントstring_to_listでローカル変数のアドレスを取得しています(ほとんどの最新の実装ではスタックに保存されています):

head = &c;

次に、そのアドレスをここに返します。

return head;

if ステートメントの終了後、変数cは存在しなくなります。これは未定義の動作です。C99 ドラフト標準セクションオブジェクトの保存期間パラグラフ2には、次のように記載されています。6.2.4

[...]オブジェクトが有効期間外に参照された場合、動作は未定義です。[...]

于 2013-05-16T17:41:41.403 に答える