Search code examples
cmemory-managementstructvalgrind

Resolving Invalid Writes errors in valgrind


I'm new to using valgrind and programming in C in general. I'm trying to make sense of the following valgrind message

==6225== Invalid write of size 4
==6225==    at 0x10000144D: handle_client (server.c:82)
==6225==    by 0x10000186A: main (server.c:201)
==6225==  Address 0x100a83248 is 0 bytes after a block of size 8 alloc'd
==6225==    at 0x10000BE81: malloc (vg_replace_malloc.c:302)
==6225==    by 0x100001431: handle_client (server.c:80)
==6225==    by 0x10000186A: main (server.c:201)
==6225== 
==6225== Invalid write of size 4
==6225==    at 0x100001458: handle_client (server.c:83)
==6225==    by 0x10000186A: main (server.c:201)
==6225==  Address 0x100a8324c is 4 bytes after a block of size 8 alloc'd
==6225==    at 0x10000BE81: malloc (vg_replace_malloc.c:302)
==6225==    by 0x100001431: handle_client (server.c:80)
==6225==    by 0x10000186A: main (server.c:201)

It resolves to this of code, in which I'm trying to allocate a struct (ClientContext)

#define DEFAULT_CC_CHANDLES 4
... 
[78]    // create the client context here
[79]    ClientContext* client_context = NULL;
[80]    client_context = malloc( sizeof(client_context) );
[81]    client_context->chandle_table = malloc( sizeof(GeneralizedColumnHandle) * DEFAULT_CC_CHANDLES );
[82]    client_context->chandles_in_use = 0;
[83]    client_context->chandle_slots = DEFAULT_CC_CHANDLES;

and the definition of that struct is:

typedef struct ClientContext {
    GeneralizedColumnHandle* chandle_table;
    int chandles_in_use;
    int chandle_slots;
    int client_fd;
} ClientContext;

So what's exactly is causing the invalid write here? Am I not allocating enough space for the struct? Should I be checking if alloc returns a valid pointer first?


Solution

  • You are passing the size of a pointer to malloc() and that is not enough, try

    client_context = malloc(sizeof *client_context);
    

    The reason your code doesn't work is because sizeof client_context is equal to sizeof(void *) which is not the same as sizeof(ClientContext).

    Also, always check that malloc() actually succeeded.