Valgrind错误:malloc时读/写无效

时间:2015-06-24 17:25:01

标签: c malloc valgrind free

Valgrind在下面的代码中给出了以下错误: 写入大小为8的无效:地址XX是一个大小为33的块中的32字节

/*The function allocate memory and clean it for further use.*/
static void *ft_mal(size_t size)
{
    void    *ret;
    char    *tmp;

    ret = malloc(size); /*LINE WITH ERROR*/
    if (!ret)
        return (NULL);
    tmp = ret;
    while (size) {
       *tmp = 0;
        tmp++;
        size--;
    }
    return (ret);
}

我在下面的代码中使用了这个函数,我在注释行上也有两个无效的写入大小为8 错误:

/*Splits a string into an array of strings*/
char            **ft_splt(const char *s, char c)
{
    char    **ret;
    char    *str;
    int     i;

    i = ct_wd(s, c);
    ret = (char **)ft_mal(sizeof(*ret) * i + 1);
    str = (char *)ft_mal(sizeof(*str) * ct_c(s, c) + i);
    i = 0;
    while (*s) {
        while (*s && *s == c)
            s++;
        ret[i++] = (*s ? str : '\0'); /*LINE WITH ERROR*/
        while (*s && *s != c)
            *str++ = *s++;
        if (*s)
            *str++ = '\0';
    }
    ret[i] = 0; /*LINE WITH ERROR*/
    return (ret);
}

我不明白为什么会产生错误,因此也不知道如何解决它们。因此,当我释放malloc时,我有一个错误。

如何解决这些无效的读/写错误?

修改

根据需要,我提供更多代码。 ct_wd和ct_c分别计算字符串参数中的单词数和字符数,以便创建正确大小的malloc。

static int      ct_wd(const char *s, char c)
{
    int     nb;

    nb = 0;
    while (*s) {
        while (*s && *s == c)
            s++;
        while (*s && *s != c)
            s++;
        nb = (*(s - 1) != c ? nb + 1 : nb);
    }
    return (nb);
}

static int      ct_c(const char *s, char c)
{
    int     nb;

    nb = 0;
    while (*s) {
        if (*s != c)
            nb++;
        s++;
    }
    return (nb);
}

这是一个main.c示例:

int                 main()
{
    char    s[] = "lut:les:enf:?  ";
    char    **ret;
    int     i = 0;

    ret = ft_splt(s, ':');
    while (ret[i]) {
        printf("[Resultat :]\n");
        i++;
    }
    /* free all malloced pointer */
    return (0);
}

编辑:解决方案

如下所述,有一个错误:

ret = (char **)ft_mal(sizeof(*ret) * i + 1);

应改为:

ret = (char **)ft_mal(sizeof(*ret) * (i + 1));

执行时我仍有一个段错误。似乎删除了这一行:

ret[i] = 0;

删除了valgrind错误和segfault。 我理解这行不是必要的,因为ft_mal已经清理了内存,但我真的不明白为什么这两者都会在valgrind中产生写入错误并使我出现seg错误。

1 个答案:

答案 0 :(得分:4)

向后工作:

最后的错误很简单。我认为你打算ret成为一个零终止的char *数组。但你这样分配它:

ret = (char **)ft_mal(sizeof(*ret) * i + 1);

如果您想要终止null的其他一个条目,则需要i + 1*ret条目,即。

ret = (char **)ft_mal(sizeof(*ret) * (i + 1));

前面的错误更难。这一行:

ret[i++] = (*s ? str : '\0'); /*LINE WITH ERROR*/

令人困惑。 ret[i++]似乎是char *。但您似乎是在char中进行复制。你在这里做什么意思?使用-Wall进行编译时会发生什么?我打赌你看到了警告。

这一行:

ret = malloc(size); /*LINE WITH ERROR*/

看起来不太可能产生你建议的valgrind错误。我建议使用-O0 -g -Wall进行编译,并在修复其他位后再次尝试,并仔细检查行号。

它产生free()错误,因为你永远不会free()