Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Invalid write,read when allocating memory in c

I have this function split_text that takes in a char array text and attempts to split it into sub-arrays using the token as the split value, res is an array of pointers to each of the sub-strings

int split_text(char * text, char * token, char ** res)
{
    int x =0;
    char * tmp = strtok(text , token);
    while (tmp != NULL)
    {
        res[x] = malloc(1024);
        strcpy(res[x], tmp);
        x++;
        *res = realloc(*res, sizeof(char*)*(x+1));
        tmp = strtok(NULL , token);
    }
    return x;
}

int main()
{
    char text[] = "Hello world this is elliot";

    char ** ptr = (char**)malloc(sizeof(char*));

    int x = split_text(text, " ", ptr);

    
    for (int i =0; i< x; i++)
        printf("%s\n", ptr[i]);
    
    return 0;
}

when compiling this code it works fine as in it displays the sub-strings each on a new line but when ran with valgrind, I get many Invalid write of size 8 and Invalid read of size 8

Here is the full valgrind output

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

==74210== Memcheck, a memory error detector
==74210== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==74210== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==74210== Command: ./a.out
==74210== 
==74210== Invalid write of size 8
==74210==    at 0x1091D0: split_text (split.c:23)
==74210==    by 0x1092B2: main (split.c:38)
==74210==  Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210==    at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210==    by 0x109294: main (split.c:36)
==74210== 
==74210== Invalid read of size 8
==74210==    at 0x1091E7: split_text (split.c:24)
==74210==    by 0x1092B2: main (split.c:38)
==74210==  Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210==    at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210==    by 0x109294: main (split.c:36)
==74210== 
Hello
==74210== Invalid read of size 8
==74210==    at 0x1092D3: main (split.c:42)
==74210==  Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210==    at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210==    by 0x109294: main (split.c:36)
==74210== 
world
this
is
elliot
==74210== 
==74210== HEAP SUMMARY:
==74210==     in use at exit: 4,152 bytes in 6 blocks
==74210==   total heap usage: 12 allocs, 6 frees, 6,312 bytes allocated
==74210== 
==74210== LEAK SUMMARY:
==74210==    definitely lost: 4,104 bytes in 5 blocks
==74210==    indirectly lost: 48 bytes in 1 blocks
==74210==      possibly lost: 0 bytes in 0 blocks
==74210==    still reachable: 0 bytes in 0 blocks
==74210==         suppressed: 0 bytes in 0 blocks
==74210== Rerun with --leak-check=full to see details of leaked memory
==74210== 
==74210== ERROR SUMMARY: 12 errors from 3 contexts (suppressed: 0 from 0)
==74210== 
==74210== 4 errors in context 1 of 3:
==74210== Invalid read of size 8
==74210==    at 0x1092D3: main (split.c:42)
==74210==  Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210==    at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210==    by 0x109294: main (split.c:36)
==74210== 
==74210== 
==74210== 4 errors in context 2 of 3:
==74210== Invalid read of size 8
==74210==    at 0x1091E7: split_text (split.c:24)
==74210==    by 0x1092B2: main (split.c:38)
==74210==  Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210==    at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210==    by 0x109294: main (split.c:36)
==74210== 
==74210== 
==74210== 4 errors in context 3 of 3:
==74210== Invalid write of size 8
==74210==    at 0x1091D0: split_text (split.c:23)
==74210==    by 0x1092B2: main (split.c:38)
==74210==  Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210==    at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210==    by 0x109294: main (split.c:36)
==74210== 
==74210== ERROR SUMMARY: 12 errors from 3 contexts (suppressed: 0 from 0)

I know that it is reading and writing from invalid memory places but it still outputs the split-ed text as sub-strings

Why do I get these errors and how do I fix them?

>Solution :

At least this statement

*res = realloc(*res, sizeof(char*)*(x+1))

that is equivalent to

res[0] = realloc(res[0], sizeof(char*)*(x+1))

does not make a sense.

It always reallocates the first element of the array of pointers pointed to by the pointer res.

As a result the array pointed to by the pointer res has only one element allocated in main.

So this call strcpy

strcpy(res[x], tmp);

invokes undefined behavior at least when x is not equal to 0.

Pay attention to that if you want to change the pointer ptr declared in main within the function split_text then you need to pass it to the function by reference. That is the third parameter of the function should be declared like

int split_text(char * text, char * token, char *** res);

As for the function definition then you need to allocate memory for a pointer for each new element and also to allocate a character array pointed to by the pointer where a substring will be copied.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading