3

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)

trincot
  • 317,000
  • 35
  • 244
  • 286
Odko
  • 151
  • 1
  • 1
  • 8

2 Answers2

3

from the libconfig api manual

Storage for the string returned by config_lookup_string() is managed by the library and released automatically when the setting is destroyed or when the setting's value is changed; the string must not be freed by the caller.

So you need to copy the pointer returned by config_lookup_string() into another array if you want to use it after config_destroy()

Ingo Leonhardt
  • 9,435
  • 2
  • 24
  • 33
2

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 */
mshildt
  • 8,782
  • 3
  • 34
  • 41
  • Thank you for your answer. looks like i have to free that conf_data.timeformat after use. Is there any other option other than strdup ? – Odko May 06 '15 at 13:44
  • @akiD Yes, technically you must free the conf_data.timeformat after use to avoid a memory leak, however if this is global config data that survives throughout the entire life of the program, neglecting to free() it at program exit time isn't a big deal IMO. There are other ways to copy a string (memcpy, etc) but strdup() is the most straight forward. – mshildt May 06 '15 at 14:10