Search code examples
cstructenumsvalgrinddynamic-memory-allocation

C: valgrind shows invalid write for double pointer enum in struct


In my test.c, I have:

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

enum MyEnum{
    H1 = '#',
    H2 = '$'
};

typedef struct {
    enum MyEnum** myenum;
    int myint;
    char *s;
} MyStruct;

MyStruct* somefunction(const char* fp){
    FILE* file = fopen(fp, "r");
        if(!file){
        fprintf(stderr, "Error %s not found", fp);
        exit(-1);
    }
    char line[100] = {0};
    int i = 0;
    fgets(line, 100, file);
    sscanf(line, "%i", &i);
    MyStruct* strct = (MyStruct *) malloc(sizeof(strct));
    strct->myint = i;
    printf("%i\n", strct->myint);

    fclose(file);
    free(strct);
    return strct;
}


int main(int argc, char** argv){
  char* fp = argv[1];
  somefunction(fp);
  bool run = true;
  while(run){
    char entry = fgetc(stdin);
    
    switch(entry){ 
      case 'q' :{
        run = false;
        break;                      
      }
    }
  }
}

My test.txt contains:

1234
5678

Running Valgrind with give:

1234
q
==2030==
==2030== HEAP SUMMARY:
==2030== HEAP SUMMARY:
==2030==     in use at exit: 0 bytes in 0 blocks
==2030==   total heap usage: 5 allocs, 5 frees, 6,704 bytes allocated
==2030==
==2030== All heap blocks were freed -- no leaks are possible
==2030==
==2030== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
==2030==
==2030== 1 errors in context 1 of 2:
==2030== Invalid read of size 4
==2030==    at 0x108AA9: somefunction (in /root/SokobanTechDev/test)
==2030==    by 0x108B03: main (in /root/SokobanTechDev/test)
==2030==  Address 0x51de2f8 is 0 bytes after a block of size 8 alloc'd
==2030==    at 0x4C2D0AF: malloc (vg_replace_malloc.c:381)
==2030==    by 0x108A93: somefunction (in /root/SokobanTechDev/test)
==2030==    by 0x108B03: main (in /root/SokobanTechDev/test)
==2030==
==2030==
==2030== 1 errors in context 2 of 2:
==2030== Invalid write of size 4
==2030==    at 0x108AA2: somefunction (in /root/SokobanTechDev/test)
==2030==    by 0x108B03: main (in /root/SokobanTechDev/test)
==2030==  Address 0x51de2f8 is 0 bytes after a block of size 8 alloc'd
==2030==    at 0x4C2D0AF: malloc (vg_replace_malloc.c:381)
==2030==    by 0x108A93: somefunction (in /root/SokobanTechDev/test)
==2030==    by 0x108B03: main (in /root/SokobanTechDev/test)

Why is valgrind giving me an invalid write after defining enum MyEnum? In my struct, if I comment enum MyEnum** myenum;, those contexts disappears. I theorize that he is allocating 2 pointers (of 8 bytes each) to H1 and H2, but isn't the malloc supposed to take care of that ?

I tried to look for some answers like here and here but I can't seem anything related to double pointers.

Thank you in advance


Solution

  • There are at least two bugs within the function.

    The first one is an incorrect memory allocation

    MyStruct* strct = (MyStruct *) malloc(sizeof(strct));
    

    You need to write either

    MyStruct* strct = (MyStruct *) malloc(sizeof(*strct));
    

    or

    MyStruct* strct = (MyStruct *) malloc(sizeof(MyStruct));
    

    And returning the pointer with an invalid value after call free

        //...
        free(strct);
        return strct;
    }
    

    does not make a sense.