Search code examples
cinitializationmallocvalgrindheap-memory

Valgrind - Use of uninitialised value allocated on the heap


I am trying to create an 'array of pointers' to a custom struct, dynamically allocating the memory since I am not sure of the size this array must have. While initializing the data, I can access the custom struct at each index without problem.

Once I get outside the initializing loop, suddenly valgrind tells me that I am using an unitialized value of size 8. I really don't understand why this is the case. Using calloc to initialize everything to null did not (as I expected) helped either. Using an array of pointers like FuncSym *f_sym[NB_LINES]; and changing what needed to be changed did not help either. I do think though FuncSym_create(...) initializes everything correctly.

...
unsigned long count = 0;
FuncSym **f_sym = (FuncSym**)malloc(NB_LINES * sizeof(FuncSym*));
unsigned long cur_max = NB_LINES;

char *line = NULL;
size_t len = 0;
ssize_t nread;
const char *del = " ";
while((nread = getline(&line, &len, tmp)) != -1) {
    if(true) { // make example smaller
        if(++count < cur_max) {
            f_sym[count] = FuncSym_create("name", 10, 10);
            printf("No Problem Here! \n Addr: %lu", FuncSym_addr(f_sym[count]));
        } else { // make sure size fits
            cur_max = 2*cur_max;
            FuncSym **tmp = (FuncSym**)realloc(f_sym, cur_max*sizeof(FuncSym*));
            if(!tmp){
                for(unsigned long i = 0; i < count; i++)
                    FuncSym_free(f_sym[i]);
                free(f_sym);
                exit(EXIT_FAILURE);
            }
            f_sym = tmp;
            f_sym[count] = FuncSym_create("name", 10, 10);
        }
    }
}
for(unsigned long i = 0; i <= count; i++){
    printf("Unitialised value here: %lu\n\n", FuncSym_addr(f_sym[i]));
}
...

struct FuncSym {
    char *name;
    unsigned long addr;
    unsigned long size;
};

FuncSym *FuncSym_create(char *sym_name, unsigned long addr, unsigned long size){
    assert(sym_name != NULL);
    FuncSym *f_sym = (FuncSym*)malloc(sizeof(FuncSym));
    if(!f_sym) stack_mem_error();
    f_sym->name = strdup(sym_name);
    f_sym->addr = addr;
    f_sym->size = size;
    return f_sym;
}
unsigned long FuncSym_addr(FuncSym *f_sym) { return f_sym->addr; }

Solution

  • f_sym[0] was never set because the counter was incremented (++counter) before entering the if statement. When later accessed f_sym[0] was indeed uninitialized. Fixing counter solved all problems. Just in case anyone ever reads this question.

    ...
    while((nread = getline(&line, &len, tmp)) != -1) {
        if(true) { // make example smaller
            if(count+1 < cur_max) {
                f_sym[count++] = FuncSym_create("name", 10, 10);
                printf("No Problem Here! \n Addr: %lu", FuncSym_addr(f_sym[count]));
            } else { // make sure size fits
                cur_max = 2*cur_max;
                FuncSym **tmp = (FuncSym**)realloc(f_sym, cur_max*sizeof(FuncSym*));
                if(!tmp){
                    for(unsigned long i = 0; i < count; i++)
                        FuncSym_free(f_sym[i]);
                    free(f_sym);
                    exit(EXIT_FAILURE);
                }
                f_sym = tmp;
                f_sym[count++] = FuncSym_create("name", 10, 10);
            }
        }
    }
    ...