[C] help with string handling memory leak

Ok, so I've been trying to figure out my fualt in this code for probably a week now.

Hopefully somebody will see what I couldn't see.

Anyways, any help would be greatly appreciated. Lets begin.

void serverStatus( const char* data )
{
    char* s          ;
    int   i, l = 0   ;
    char* tok        ;
    int   tokcount   ;
    hash_t srv[32]   ;
    bzero(srv, sizeof(srv));

    s = strdup( data+20 );
    strcpy(s, data+20);

    // Tokenize
    for(i = 0, tok = strtok( s, "\\"); tok; tok = strtok( NULL, "\\"))
    {
        l = ( l ? 0 : 1 );
        if( l ) // if its a variable
            strcpy( srv.key, tok );

        else    // if its a value
        {
            strcpy( srv.val, tok );
            ++i;
        }
    }

    // Dump server info
    tokcount = i;
    i = 0;
    while( i < tokcount )
    {
        if ( strncmp( srv.key, SRV_HOSTNAME, strlen(SRV_HOSTNAME) ) == 0 )
        {
            char* tmp = sanitizeString(srv.val);
            printf( "%s %s\n", srv.key, srv.val );
            free(tmp);
        }
        else if ( strncmp( srv.key, SRV_MAPNAME,  strlen(SRV_MAPNAME) ) == 0 )
        {
            printf( "%s %s\n", srv.key, srv.val );
        }        
        ++i;
    }
}

This is my code in question. Although I understand the problem could be prior in my network handling. ( we can explore more on this later. )

So what I know is that the code 'generally', if it does at all, crashes in the while loop.

Freeing my pointer 's' always crashes, ALWAYS. this bothers me a bit.

finally when i do print values, sometimes it prints stuff that isn't supposed to be there. ( ie memory issue )

the hash_t type looks as follows.

typedef struct info_s {
    char key[256];
    char val[256];
    } hash_t;

none of the values that we tokenize are larger than 255 characters.

Lastly full code is accessible if you would like to see it crash in real time.
( qquery.googlecode.com )

Thanks much for any insight you can provide.
~vroemer

You don't need both strdup and strcpy and since free goes with strdup get rid of the strcpy and the code should be fine. Btw strcpy expects its first argument to be a pointer to an array of char. In your code s is just a pointer to char so there is no room is s to store the string that data+20 points to. So don't even think about keeping strcpy unless s is really char s[1024], that is an array.

Oh, thats interesting I don't remember leaving that there. Thanks for catching that. ok

Ok then, I have a small question to impose onto this then. If I add this to the very end of the function. Why does it cause a memory leak?

    free(s); 
    s = NULL;

    s = strdup( data+19 );
    while((*s) && (*s != '\n'))
    {
        s++;
    }
    s++; // skip the newline
    printf( "%s", s);
    free(s);

is it because I reasign s? Becuase I reuse data? If always crashes on that final 'free'

valgrind reports, with and without the final free, a loss of the same amount of bytes.

EDIT:
I think I know why, because I moved the pointer right? The fix would be to make an aditional pointer to point at the beginning i believe.

I was referring to this code...

s = strdup( data+20 );  /* don't need both strcpy and strdup */
strcpy(s, data+20);     /* get rid of the strcpy */

Yes it's because free expects the exact same pointer that was returned by the call to strdup. By incrementing s you lost the original pointer returned by strdup.

That's right create another pointer that points to the same place as s and increment that one instead of s. This way you won't have any problems when you try to free s.