1

I'm coding a split function, this is the code:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char **split ( const char *s1, const char *s2) {

    char **lista;
    char *aux = s1;
    char *token_Ptr;
    int i = 0;
    
    lista = (char **) malloc (sizeof (char *));
    token_Ptr = strtok(aux, s2);
    lista[i] = token_Ptr;
    while(token_Ptr != NULL)
    {
        lista = (char **)realloc(lista, sizeof(char*) * (i + 1));
        token_Ptr = strtok(NULL, s2);
        i++;
        lista[i] = token_Ptr;
    }
    return lista;
}

int main ( int argc , char *argv[]) {

    char **MILISTA;
    int i;

    if (argc==2) {
        printf ("Cadena: '%s'\n",argv[1]);
        MILISTA= split(argv[1]," ");
        i=0;
        puts("----------------TOKENS------------");
        while (MILISTA[i]!=NULL) {
            printf("%s, " , MILISTA[i++]);
        }
        printf("\n");
        puts("----------------FIN---------------");
    }
    return 0;
}

But i've got some errors:

facu@linux:~/projects/spliting/bin/Debug$ ./spliting "HOLA MUNDO COMO s"
Cadena: 'HOLA MUNDO COMO s'
*** glibc detected *** ./spliting: realloc(): invalid next size: 0x09e12008 ***
======= Backtrace: =========
/lib/libc.so.6(+0x6c501)[0x17c501]
/lib/libc.so.6(+0x71c6d)[0x181c6d]
/lib/libc.so.6(realloc+0xe3)[0x181f53]
./spliting[0x8048573]
./spliting[0x80485fa]
/lib/libc.so.6(__libc_start_main+0xe7)[0x126ce7]
./spliting[0x8048471]
======= Memory map: ========
00110000-00267000 r-xp 00000000 08:06 8526       /lib/libc-2.12.1.so
00267000-00269000 r--p 00157000 08:06 8526       /lib/libc-2.12.1.so
00269000-0026a000 rw-p 00159000 08:06 8526       /lib/libc-2.12.1.so
0026a000-0026d000 rw-p 00000000 00:00 0 
00573000-0058d000 r-xp 00000000 08:06 251        /lib/libgcc_s.so.1
0058d000-0058e000 r--p 00019000 08:06 251        /lib/libgcc_s.so.1
0058e000-0058f000 rw-p 0001a000 08:06 251        /lib/libgcc_s.so.1
0065a000-0065b000 r-xp 00000000 00:00 0          [vdso]
007f1000-00815000 r-xp 00000000 08:06 8577       /lib/libm-2.12.1.so
00815000-00816000 r--p 00023000 08:06 8577       /lib/libm-2.12.1.so
00816000-00817000 rw-p 00024000 08:06 8577       /lib/libm-2.12.1.so
00c2d000-00d0c000 r-xp 00000000 08:06 660319     /usr/lib/libstdc++.so.6.0.14
00d0c000-00d10000 r--p 000de000 08:06 660319     /usr/lib/libstdc++.so.6.0.14
00d10000-00d11000 rw-p 000e2000 08:06 660319     /usr/lib/libstdc++.so.6.0.14
00d11000-00d18000 rw-p 00000000 00:00 0 
00e86000-00ea2000 r-xp 00000000 08:06 8518       /lib/ld-2.12.1.so
00ea2000-00ea3000 r--p 0001b000 08:06 8518       /lib/ld-2.12.1.so
00ea3000-00ea4000 rw-p 0001c000 08:06 8518       /lib/ld-2.12.1.so
08048000-08049000 r-xp 00000000 08:08 262453     /home/facu/projects/spliting/bin/Debug/spliting
08049000-0804a000 r--p 00000000 08:08 262453     /home/facu/projects/spliting/bin/Debug/spliting
0804a000-0804b000 rw-p 00001000 08:08 262453     /home/facu/projects/spliting/bin/Debug/spliting
09e12000-09e33000 rw-p 00000000 00:00 0          [heap]
b7700000-b7721000 rw-p 00000000 00:00 0 
b7721000-b7800000 ---p 00000000 00:00 0 
b7870000-b7873000 rw-p 00000000 00:00 0 
b7888000-b788b000 rw-p 00000000 00:00 0 
bf834000-bf855000 rw-p 00000000 00:00 0          [stack]
Abortado

If i only parse: "HOLA MUNDO COMO" the program runs correctly...

How should i solve it?

1
  • do you think that my function is good? some advice? Commented Feb 19, 2011 at 14:24

3 Answers 3

2

Learn to use valgrind. This is one of the most useful tool to diagnose these kind of errors.

$valgrind ./a.out "HOLA MUNDO COMO s"
==4949== Memcheck, a memory error detector
==4949== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==4949== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==4949== Command: ./a.out HOLA\ MUNDO\ COMO\ s
==4949== 
Cadena: 'HOLA MUNDO COMO s'
==4949== Invalid write of size 8
==4949==    at 0x40070B: split (a.c:20)
==4949==    by 0x40076B: main (a.c:32)
==4949==  Address 0x518a098 is 0 bytes after a block of size 8 alloc'd
==4949==    at 0x4C245E2: realloc (vg_replace_malloc.c:525)
==4949==    by 0x4006DC: split (a.c:17)
==4949==    by 0x40076B: main (a.c:32)
==4949== 
----------------TOKENS------------
==4949== Conditional jump or move depends on uninitialised value(s)
==4949==    at 0x4007BF: main (a.c:35)

what this thing says, is that, on line 20, you tried to write à pointer after the end of your table.

which is true : you allocate a table of size i+1, then you increment i and you access table[i], which is not allocated. For example, The first time you enter the loop, you reallocate a table of 1 chars* (so you're not growing it), and you access a second element of your table. the second time you enter the loop, you grow your array to a size of 2 and you access the third element/

the second error, on line 35, mean that your MILISTA table have some parts that are not initialized because of the wrong behaviour of the first loop.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! I will try to learn to use valgrind! Very usefull your answer!
2

strtok modifies the source string. You can't modify the argument string (it's read only). Copy the original string in another string. And when you realloc, instead of +1 use +2 (when i = 0, you already have an element).

This:

char **split ( const char *s1, const char *s2) {

    char **lista;
    char *aux = (char*)malloc(strlen(s1) + 1);
    strcpy(aux, s1);
    char *token_Ptr;
    int i = 0;

    lista = (char **) malloc (sizeof (char *));
    token_Ptr = strtok(aux, s2);
    lista[i] = token_Ptr;
    i++;
    while(token_Ptr != NULL)
    {
        lista = (char **)realloc(lista, sizeof(char*) * (i + 1));
        token_Ptr = strtok(NULL, s2);
        lista[i] = token_Ptr;
        i++;
    } 
    return lista;
}

You will have 2 pointers to free: free(lista[0]) and free(lista).

This function is not good because it allocates memory. Very rarely a function should alloc memory. No, there isn't any solution to this problem :-) You simply must be careful to free the allocated memory.

Comments

1

You shouldn't change the content of argv (note that strtok will modify the string passed).

The rest of the function is almost correct, however you are calling realloc to make space for (i+1) elements while i is still 0. So basically you are allocating space for one pointer less than needed. Just move i++; to the beginning of the loop and everything is fine.

1 Comment

Thanks for the first advice! I will take it!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.