4
votes

Valgrind gives me the following error in the below code: Invalid write of size 8 : Address XX is 32 bytes inside a block of size 33 alloc'd

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

I use this function in the below code where I also have two Invalid write of size 8 error on commented lines:

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

I don't get why it produces the errors and therefore don't know how to solve them either. Consequently I have an error when I free the mallocs.

How do I have to do to solve these invalid read / write errors ?

Edit:

As required I give a little more code. ct_wd and ct_c respectively count the number of words and the number of characters in the string arguments in order to create the right sized 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);
}

Here is a main.c example:

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

Edit: SOLUTION

As mentionned below there was a mistake:

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

should instead be:

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

I still had a seg fault on execution. Seems like removing this line :

ret[i] = 0;

removed both the valgrind error and the segfault. I understand this line was not really necessary as ft_mal already cleaned the memory, still I don't really get why this both produced a write error in valgrind and made me seg fault.

1
Post an SSCCE if you expect people to help you debug this. Its likely that you have an off-by-one error in your routines that calculate how much memory to allocate.Chris Dodd
Particularly, what do ct_wd and ct_c do? If you could provide something with a dummy implementation of them and a main() function, this would be far easier to debug.abligh
Is it possible you have redefined malloc() somehow?wallyk
It seems ft_mal() is an implementation of malloc() + memset().alvits
Yes, this is is exactly what it is. My code is part of a school project where the use of the named functions above is forbidden.valvince

1 Answers

4
votes

Working backwards:

The final error is easy. I think you intend ret to be an array of char * that is zero terminated. But you allocate it like this:

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

If you want one more entry for the terminating null you need i + 1 entries of size *ret, i.e.

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

The preceding error is harder. This line:

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

is confusing. ret[i++] appears to be a char *. But you appear to be copying in a char. What did you mean to do here? What happens when you compile with -Wall? I bet you see a warning.

This line:

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

looks very unlikely to produce the valgrind error you suggest. I suggest compiling with -O0 -g -Wall and trying again once you've fixed the other bits up, and carefully checking the line numbers.

It's producing free() errors as you never free() anything.