首页 > 解决方案 > valgrind 在分配的内存中写入大小为 8 的无效

问题描述

我正在尝试将新节点添加到我的链表中,但它会出现内存错误

我的结构和全局变量:

typedef struct word word;

struct word
{
    char str[256];
    word *next;
};

word *head = NULL;
word *cur = NULL; 

功能 :

int addWord(char * str)
{
    word *w = calloc(1, sizeof(w));

    if(w == NULL)
    {
        return 0;
    }  
    strcpy(w->str, str);

    if(cur == NULL)
    {
        cur = w;
        head = w;
    }
    else
    {
puts("4");
        cur->next = w;
puts("5");
        cur = w;
puts("6");    
    }
    return 1;
}

结果是:

...
4
5
6
4
==73913== Invalid write of size 8
==73913==    at 0x109425: addWord (in /home/mz37/programming/godaphy/bin/godaphy.out)
==73913==    by 0x109696: parseLine (in /home/mz37/programming/godaphy/bin/godaphy.out)
==73913==    by 0x109351: main (in /home/mz37/programming/godaphy/bin/godaphy.out)
==73913==  Address 0x4a6a880 is 96 bytes inside an unallocated block of size 4,188,096 in arena "client"
==73913== 
5
6

我仍在寻找错误,我还没有找到它

标签: cpointersdata-structures

解决方案


word *w = calloc(1, sizeof(w));

w变量是word 指针类型,因此最多可能是四个或八个字节。如果我们最终使用 128 位机器,它可能会更大,但要达到 2000 多位还需要一段时间 :-)

你可能想做:

word *w = calloc(1, sizeof(*w));
//            note this ___^

的类型*w是实际的类型word,这是您尝试执行的正确大小。


而且,顺便说一句,您可能想考虑盲目地将给定的任何字符串复制到只能容纳 256 个字符的内存块中的智慧。更安全的选择是:

strncpy(w->str, str, sizeof(w->str) - 1);
// Would normally also do something like:
//     w->str[sizeof(w->str) - 1] = '\0';
// but calloc() makes that superfluous.

结果函数(包括紧缩)将遵循以下几行:

int addWord(char *str) {
    word *w;

    // Option to fail if string too big, rather than truncate.

    //if (strlen(str) >= sizeof(w->str)
    //    return 0;

    // Allocate and check.

    if ((w = calloc(1, sizeof(*w)))  == NULL)
        return 0;

    // Copy in string, truncate if too big.

    strncpy(w->str, str, sizeof(w->str) - 1);

    // Make new list if currently empty, otherwise add it, then flag success.

    if(cur == NULL) {
        cur = head = w;
    } else {
        cur->next = w;
        cur = w;
    }

    return 1;
}

推荐阅读