【问题标题】:Valgrind error: invalid read/write when mallocValgrind 错误:malloc 时读/写无效
【发布时间】:2015-09-11 01:02:10
【问题描述】:

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);
}

我在下面的代码中使用了这个函数,在注释行中我也有两个 Invalid write of size 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 错误和段错误。 我知道这条线并不是真正必要的,因为 ft_mal 已经清理了内存,但我仍然不明白为什么这会在 valgrind 中产生写入错误并使我出现段错误。

【问题讨论】:

  • 如果您希望人们帮助您调试此问题,请发布SSCCE。在计算要分配多少内存的例程中,您可能有一个错误。
  • 特别是ct_wdct_c 做什么?如果您可以提供一些具有它们的虚拟实现和main() 函数的东西,这将更容易调试。
  • 你有没有可能以某种方式重新定义了malloc()
  • 看来ft_mal()malloc() + memset() 的实现。
  • 是的,这正是它的本质。我的代码是一个学校项目的一部分,其中禁止使用上述命名函数。

标签: c malloc valgrind free


【解决方案1】:

向后工作:

最后的错误很容易。我认为您打算将 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() 任何东西。

【讨论】:

  • 感谢您的帮助。我曾经说过,我将“i + 1”更正为明显的“(i + 1)”......我 malloc 的大小等于句子中的字符数 + 字数 x char 的大小 (\0)。然后我复制大 malloc 中的单词减去拆分字符,并在每个单词的末尾添加一个 \0。 “ret[i++] = (*s ? str : '\0');”这一行使 ret 数组的每个单元格都指向句子的开头。
猜你喜欢
  • 2013-02-04
  • 2015-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多