C中的链表没有工作Valgrind错误

时间:2015-03-20 20:55:12

标签: c linked-list valgrind

该程序应该将文件的单词读取到链表。我得到了链接列表,但现在我遇到了另一个错误。使用非常大的文件时,我遇到了分段错误。

它适用于较小的列表(3-10个单词),但不适用于较大的列表。

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

typedef struct node //struct for linked list
{
    char* word;
    struct node* next;
}
node;  

int main (void)
{        
    char* dictfile = "large";

    FILE* dict = fopen(dictfile, "r");

    if (dict == NULL)
        return 1;

    node* head = NULL;       

    char* oneword = malloc(sizeof(node));  //to store the word from fgets()

    while ((fscanf (dict, "%s", oneword)) > 0)
    {                                        
        node* temp = (node*)malloc(sizeof(node));

        char* tempword = (char*)malloc(sizeof(node)); //gives me a new pointer to store the string (as pointed out by Antione)

        strcpy(tempword, oneword);

        temp->word = tempword;

        printf("%s\n", temp->word);     //prints the value (just for debug)

        temp->next = head;            
        head = temp;             
    }

    node* temp = (node*)malloc(sizeof(node));
    temp = head;

    while(temp != NULL)    //loop to print the linked list
    {           
        printf("traverse %s\n", temp->word);    //prefix 'ing traverse to know its a linked list
        temp = temp->next;
    }

    free(head);
    free(temp);
    fclose(dict);

    printf("SUCCESS!!\n");      

}    

结果如下:

./tempeol
.............lots of words then the below
acceptor
acceptor's
tempeol: malloc.c:2372: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 *(sizeof(size_t))) - 1)) & ~((2 *(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long) old_end & pagemask) == 0)' failed.
Aborted (core dumped)

Valgrind在几个地方显示无效写入。

一个是strcpy()的位置。我必须考虑额外的空字符来解决这个问题,但我不知道如何。

    -----Valgrind Error-----
jharvard@appliance (~/Dropbox/pset5): valgrind ./tempeol
==4709== Memcheck, a memory error detector
==4709== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==4709== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==4709== Command: ./tempeol
==4709== 
a
aaa
aaas
aachen
aalborg
==4709== Invalid write of size 1
==4709==    at 0x40DB401: _IO_vfscanf (vfscanf.c:1180)
==4709==    by 0x40E21F6: __isoc99_fscanf (isoc99_fscanf.c:34)
==4709==    by 0x8048681: main (tempeol.c:25)
==4709==  Address 0x423b1c0 is 0 bytes after a block of size 8 alloc'd
==4709==    at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==4709==    by 0x8048662: main (tempeol.c:23)
==4709== 
==4709== Invalid read of size 1
==4709==    at 0x402D4F1: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==4709==    by 0x80486D5: main (tempeol.c:31)
==4709==  Address 0x423b1c0 is 0 bytes after a block of size 8 alloc'd
==4709==    at 0x402A17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==4709==    by 0x8048662: main (tempeol.c:23)
==4709== 
aalesund

需要帮助!!

同样有趣的是:如果我将char* tempword = (char*)malloc(sizeof(node));更改为char* tempword = (char*)malloc(sizeof(node)*512);,我最终会在最后获得包含分段错误的完整链接列表。

我觉得解决方案就在于这行代码。任何想法??

=============================================== ================

感谢@DrC和@lurker,我已经有了它的工作。 Valgrind没有显示任何错误。没有分段错误。 :)

以下是需要它的人的最终工作代码:

================WORKING CODE:: SOLUTION============
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct node //struct for linked list
{
    char* word;
    struct node* next;
}
node;  

int main (void)
{        
    char* dictfile = "small";

    FILE* dict = fopen(dictfile, "r");

    if (dict == NULL)
        return 1;

    node* head = NULL;       

    char oneword[28];  //to store the word from fscanf()

    while ((fscanf (dict, "%s", oneword)) > 0)
    {                                        
        node* temp = (node*)malloc(sizeof(node));

        char* tempword = (char*)malloc(strlen(oneword)+1); //gives me a new pointer to store the string (as pointed out by Antione)

        strcpy(tempword, oneword);

        temp->word = tempword;

        //printf("%s\n", temp->word);     //prints the value (just for debug)

        temp->next = head;            
        head = temp;             
    }

    node* temp = head;

    while(temp != NULL)    //loop to print the linked list
    {           
        printf("%s\n", temp->word);    //prefix 'ing traverse to know its a linked list
        temp = temp->next;
    }

    printf("\n");

    free(head);
    //free(temp);   //no need for this (DrC)
    fclose(dict);

    printf("SUCCESS!!\n");      

}    

我现在可以睡觉了......

1 个答案:

答案 0 :(得分:1)

您有第一个问题的正确代码行。您可以根据sizeof(节点)对内存进行malloc以保存字符串。相反,它应该是strlen(oneword)+1的长度。现在,任何长字都会超出缓冲区。

char* tempword = (char*)malloc(strlen(oneword)+1);

在行中:

...}

node* temp = (node*)malloc(sizeof(node));
temp = head;

while(temp != NULL)  ...

您将temp分配给某些malloc存储,然后立即将temp设置为head - 从而泄漏存储(次要)。

非常小的项目 - 最后调用free(temp)是浪费,因为临时必须为空。