Valgrind error: invalid read/write when malloc
Valgrind error: invalid read/write when malloc
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 : '[=11=]'); /*LINE WITH ERROR*/
while (*s && *s != c)
*str++ = *s++;
if (*s)
*str++ = '[=11=]';
}
ret[i] = 0; /*LINE WITH ERROR*/
return (ret);
}
我不明白为什么它会产生错误,因此也不知道如何解决它们。因此,当我释放 mallocs 时出现错误。
我该怎么做才能解决这些无效的读/写错误?
编辑:
根据需要,我给出了更多的代码。
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 中产生写入错误并使我出现段错误。
向后工作:
最后的错误很简单。我想你打算 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 : '[=12=]'); /*LINE WITH ERROR*/
令人困惑。 ret[i++]
似乎是 char *
。但是您似乎是在 char
中复制。你来这里是什么意思?使用 -Wall
编译时会发生什么?我打赌你会看到一个警告。
这一行:
ret = malloc(size); /*LINE WITH ERROR*/
看起来不太可能产生您建议的 valgrind 错误。我建议使用 -O0 -g -Wall
进行编译,并在修复其他位后重试,并仔细检查行号。
它正在产生 free()
错误,因为你从来没有 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);
}
我在下面的代码中使用了这个函数,在注释行上还有两个 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 : '[=11=]'); /*LINE WITH ERROR*/
while (*s && *s != c)
*str++ = *s++;
if (*s)
*str++ = '[=11=]';
}
ret[i] = 0; /*LINE WITH ERROR*/
return (ret);
}
我不明白为什么它会产生错误,因此也不知道如何解决它们。因此,当我释放 mallocs 时出现错误。
我该怎么做才能解决这些无效的读/写错误?
编辑:
根据需要,我给出了更多的代码。 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 中产生写入错误并使我出现段错误。
向后工作:
最后的错误很简单。我想你打算 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 : '[=12=]'); /*LINE WITH ERROR*/
令人困惑。 ret[i++]
似乎是 char *
。但是您似乎是在 char
中复制。你来这里是什么意思?使用 -Wall
编译时会发生什么?我打赌你会看到一个警告。
这一行:
ret = malloc(size); /*LINE WITH ERROR*/
看起来不太可能产生您建议的 valgrind 错误。我建议使用 -O0 -g -Wall
进行编译,并在修复其他位后重试,并仔细检查行号。
它正在产生 free()
错误,因为你从来没有 free()
任何东西。