2

リンクリストを印刷する小さなプログラムを書いています。このリストには、文字列と次のノードへのポインタが含まれています。

リンクリストを、新しいノードを追加してデータフィールドに入力する関数に渡します。

main関数に戻ってリストの内容を印刷しようとすると、セグメンテーション違反エラーが発生しますが、関数add_nodeからノードの内容を印刷できます。

リストと文字列を関数に渡せるようにしたいのですが、関数は渡した文字列を使用して新しいノードをリストに追加する必要があります。

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

struct node
{
    char filename[25];
    struct node *next;
};

typedef struct node LISTNODE;
typedef LISTNODE *LISTNODEPTR;

void add_node(LISTNODEPTR *nFile, char *chaData);

int main (int argc, char *argv[])
{
    LISTNODEPTR nFile = NULL;

    printf("Printing list\n");

    add_node(&nFile, "file.txt");

    printf("%s\n", nFile->filename);

    free(nFile);

    return 0;
}

void add_node(LISTNODEPTR *nFile, char *chaData)
{
    LISTNODEPTR head = *nFile;
    LISTNODEPTR newNode;

    newNode = (LISTNODEPTR) malloc(sizeof (struct node));

    strcpy(newNode->filename, chaData);

    printf("%s\n", newNode->filename);

    newNode->next = head; //link next. newNode next points to head (beginning of the list). At this time (head & newNode)->2nd->3rd->NULL

    head = newNode;
}

出力:印刷リストfile.txtセグメンテーション違反

OS:Linux sisdvb02 2.6.35-28-サーバー#49-UbuntuSMP火3月1日14:55:37UTC 2011 x86_64 GNU / Linux

コンパイラ:gcc -Wall -o list list.c

4

4 に答える 4

3

nFile関数内は変更されadd_node()ません。それでもポイントしNULL、逆参照しようとするとNULL、セグメンテーション違反エラーが発生します。ところで、Valgrindを使用してそのような問題を解決してください。

関数を次のように変更します。

void add_node(LISTNODEPTR *nFile, char *chaData)
{
    LISTNODEPTR head = nFile;
    LISTNODEPTR newNode;

    newNode = (LISTNODEPTR) malloc(sizeof (struct node));

    strcpy(newNode->filename, chaData);

    printf("%s\n", newNode->filename);

    newNode->next = head; //link next. newNode next points to head (beginning of the list). At this time (head & newNode)->2nd->3rd->NULL

    head = newNode;
    nFile = head;
}
于 2013-01-17T19:27:15.380 に答える
0

nullへのポインタがあります。次に、これを別の変数に割り当てて、変数がnullを指すようにします。次に、メモリを割り当て、そのメモリをポイントします。これは、元のポインタがまだnullを指していることを変更しません。

関数の最後の行を次のように変更します

*nFile = head;

また、バッファオーバーフローのバグを変更したくない場合は、次のように変更します。

strncpy(newNode->filename, chaData, 25);
newNod->filename[24] = 0;
于 2013-01-17T19:29:50.513 に答える
0

内部では、ローカル変数のみである変数add_node()を変更します。これはの変数にheadは影響しません-制御がに戻ったときのままです。そのため、セグメンテーション違反が発生します。nFilemain()NULLmain()

の最後の行は次のようにadd_node()なります。

     *nFile = newNode;
于 2013-01-17T19:31:04.317 に答える
0

IMHOで最も重要なことは、このような障害をデバッグする方法を学ぶことです。gdbプログラムがクラッシュした場所とプログラムの状態を知るために使用すると便利です。

$ gcc -Wall -g test.c -o test
$ gdb ./test
...
(gdb) run
...
Program received signal SIGSEGV, Segmentation fault.
...
(gdb) bt
#0  __strlen_sse2 () at ../sysdeps/x86_64/multiarch/../strlen.S:32
#1  0x00007ffff7aa783c in _IO_puts (str=0x0) at ioputs.c:37
#2  0x0000000000400612 in main (argc=1, argv=0x7fffffffe6a8) at test.c:24
(gdb) frame 2
#2  0x0000000000400612 in main (argc=1, argv=0x7fffffffe6a8) at test.c:24
24      printf("%s\n", nFile->filename);
(gdb) print nFile
$1 = (LISTNODEPTR) 0x0

btプログラムがクラッシュしたときの正確な場所を示すバックトレースが表示されます。そして、私はprint nFileそれnFileがまだNULLであったことを知っています。なんで?さて、あなたは(捨てられようとしている一時変数に割り当てる)head = newNodeの最後の行として設定していることがわかります。代わりに(ポインタを介して呼び出し元の変数に割り当てる)を設定するつもりだったと思います。add_node*nfile = newNode

于 2013-01-17T19:31:25.897 に答える