Search code examples
cstructheap-memoryvalgrindlibconfig

Global struct memory error


My program's reading from config file using libconfig and saving values to the global struct. It's working fine but valgrind says there's error. And the error only shows for char pointer variable. What is that error and how to fix that ? Thank you

#include <stdio.h>
#include <libconfig.h>
#include "stdlib.h"
#define conf_file "myconf"

struct setting_data
{
    int number;
    const char* timeformat;
};
struct setting_data conf_data;
void read_config();
int main(){
    read_config();
    printf("%d @ %p\n", conf_data.number,&conf_data.number);
    printf("%s @ %p\n", conf_data.timeformat,&conf_data.timeformat);

}

void read_config(){
    config_t cfg;
    // config_setting_t *rules, *settings,*m_number,*device,*sendduration,*pin_code;
    config_init(&cfg);

    if(! config_read_file(&cfg, conf_file))
    {
        fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg),
                config_error_line(&cfg), config_error_text(&cfg));
        config_destroy(&cfg);
        exit(1);
    }
    // conf_data.number        = config_setting_get_int   (config_lookup(&cfg, "number"       ));
    config_lookup_int(&cfg,"number",&conf_data.number);
    config_lookup_string(&cfg, "timeformat", &conf_data.timeformat);
    config_destroy(&cfg);
}

==8238== Invalid read of size 1

==8238== at 0x50AFBC9: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1317)

==8238== by 0x5083972: vfprintf (vfprintf.c:1629)

==8238== by 0x508C269: printf (printf.c:35)

==8238== by 0x400993: main (test.c:16)

....

==8238== Address 0x53cdb0c is 12 bytes inside a block of size 15 free'd

==8238== ERROR SUMMARY: 43 errors from 5 contexts (suppressed: 4 from 4)


Solution

  • libconfig is passing you a pointer to its internal string storage for the timeformat value. Which then gets freed when you do a config_destroy() causing your global struct's timeformat pointer to be invalid. To avoid this strdup() the timeformat string returned to you by libconfig:

    const char *time_str;
    config_lookup_string(&cfg, "timeformat", &time_str);
    conf_data.timeformat = strdup(time_str);
    config_destroy(&cfg);
    /* conf_data.timeformat is still valid */