0

私は自分のプログラムで何がうまくいかないのかを理解するのに苦労しています。createNode関数でノードを作成し、addNodeを使用してそれらをリストの先頭に追加することにより、リンクリストを作成しようとしています。ノードを作成しようとするとプログラムが失敗し、セグメンテーション違反が発生します。

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

struct listnode {
    int line;
   char *word;
   struct lnode *next;
};


struct listnode* createNode (char* word, int line) {
  int strlen1 = strlen(word)+1;
    struct lnode *node = malloc(sizeof(struct lnode));
    node->word = malloc(sizeof(char)*strlen1);
    strcpy(node->word,word);
    node->word[strlen1] = '\0';
    node->next = NULL;
    node->line = line;
    return node;
}


void addNode (struct listnode** head, struct listnode* node) {
    if ((*head)==NULL){
    head = &node;
    }
    else if((*head)->next!=NULL){
        struct lnode *temp = *head;
        node->next = *head;
    }else if(*head!=NULL&&(*head)->next==NULL){
        (*head->next) = node;
    }
    }

valgrindを介してプログラムを実行すると、次のエラーが発生します。

==14661== Command: ./testlist
==14661== 
==14661== Invalid write of size 1
==14661==    at 0x4006E3: createNode (in /u/data/u95/testprogs/testlist)
==14661==    by 0x40091C: main (in /u/data/u95/testprogs/testlist)
==14661==  Address 0x51dc0a6 is 0 bytes after a block of size 6 alloc'd
==14661==    at 0x4C2AF5D: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64  linux.so)
==14661==    by 0x4006AF: createNode (in /u/data/u95/testprogs/testlist)
==14661==    by 0x40091C: main (in /u/data/u95/testprogs/testlist)
==14661== 
==14661== Use of uninitialised value of size 8
==14661==    at 0x40071C: addNode (in /u/data/u95/testprogs/testlist)
==14661==    by 0x400933: main (in /u/data/u95/testprogs/testlist)
==14661==  Uninitialised value was created by a stack allocation
==14661==    at 0x4008E8: main (in /u/data/u95/testprogs/testlist)
==14661== 
==14661== Invalid read of size 8
==14661==    at 0x40071C: addNode (in /u/data/u95/testprogs/testlist)
==14661==    by 0x400933: main (in /u/data/u95/testprogs/testlist)
==14661==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==14661== 
==14661== 
==14661== Process terminating with default action of signal 11 (SIGSEGV)
==14661==  Access not within mapped region at address 0x0
==14661==    at 0x40071C: addNode (in /u/data/u95/testprogs/testlist)
==14661==    by 0x400933: main (in /u/data/u95/testprogs/testlist)
==14661==  If you believe this happened as a result of a stack
==14661==  overflow in your program's main thread (unlikely but
==14661==  possible), you can try to increase the size of the
==14661==  main thread stack using the --main-stacksize= flag.
==14661==  The main thread stack size used in this run was 8388608.

私はCを初めて使用しますが、なぜこれらのエラーがスローされるのかわかりません。誰か助けてもらえますか?

4

2 に答える 2

1

の定義が見つかりませんlnode。と同じlistnodeですか?

addNode ヘッド要素を誤って設定し、長いリストのテールを正しく検出しません。それは次のようなものでなければなりません

void addNode(struct listnode** head, struct listnode* node) {
    if ((*head)==NULL){
        *head = node;
    }
    else {
        struct listnode* tail = *head;
        while (tail->next != NULL) {
            tail = tail->next;
        }
        tail->next = node;
    }
}

*head空のリストの割り当てがありませんでした。の値を設定するとhead、ローカルポインターが変更されましたが、呼び出し元のポインターは変更されませんでした。より長いリストの場合、テールを見つけるためにすべてのメンバーを反復処理する必要があります。

これにより、Use of uninitialised value of size 8エラーが修正される場合があります。そうでない場合は、を呼び出すコードを表示する必要がありますaddNode

createNodeの割り当て/初期化を簡素化できwordます

node->word = malloc(strlen(word)+1);
strcpy(node->word,word);

ヌルターミネータを設定する必要はありません-strcpyこれをコピーします。そして、William Pursellが指摘したように、これは文字列の終わりを超えて書くことを避けるため、実際には重要な変更です。これでエラーが修正されますInvalid write of size 1

于 2013-02-16T19:35:38.197 に答える
1

以下は間違っていることが保証されています。

node->word = malloc(sizeof(char)*strlen1);
...
node->word[strlen1] = '\0';

word に strlen1 バイトを割り当てるので、おそらく次のことを意味します。

node->word[strlen1 - 1] = '\0';

null バイトを書き込む必要さえないことに注意してstrcpyください。コード内の他のエラーが何であるかは明確ではありません。このエラーを修正するまで、実際に調べる価値はありません。

于 2013-02-16T19:42:15.083 に答える