Глобальная ошибка памяти структуры

Моя программа читает файл конфигурации, используя libconfig, и сохраняет значения в глобальной структуре. Он работает нормально, но valgrind говорит, что есть ошибка. И ошибка отображается только для переменной указателя char. Что это за ошибка и как ее исправить? Спасибо

#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== Неверное чтение размера 1

==8238== по адресу 0x50AFBC9: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1317)

==8238== по адресу 0x5083972: vfprintf (vfprintf.c:1629)

==8238== по 0x508C269: printf (printf.c:35)

==8238== по 0x400993: основной (test.c:16)

....

==8238== Адрес 0x53cdb0c — это 12 байтов внутри блока размером 15, освобожденных

==8238== ОБЩИЕ ОШИБКИ: 43 ошибки из 5 контекстов (исключено: 4 из 4)


person Odko    schedule 06.05.2015    source источник


Ответы (2)


libconfig передает вам указатель на свое внутреннее хранилище строк для значения timeformat. Который затем освобождается, когда вы выполняете config_destroy(), в результате чего указатель формата времени вашей глобальной структуры становится недействительным. Во избежание этого strdup() строка формата времени возвращается вам 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 */
person mshildt    schedule 06.05.2015
comment
Спасибо за ваш ответ. похоже, мне нужно освободить этот conf_data.timeformat после использования. Есть ли другой вариант, кроме strdup? - person Odko; 06.05.2015
comment
@akiD Да, технически вы должны освободить формат conf_data.timeformat после использования, чтобы избежать утечки памяти, однако, если это глобальные данные конфигурации, которые сохраняются на протяжении всей жизни программы, пренебрежение free() во время выхода из программы не является большое дело ИМО. Существуют и другие способы копирования строки (memcpy и т. д.), но strdup() является наиболее простым. - person mshildt; 06.05.2015

из руководства по libconfig API

Хранилище для строки, возвращаемой функцией config_lookup_string(), управляется библиотекой и освобождается автоматически при уничтожении параметра или при изменении значения параметра; строка не должна освобождаться вызывающей стороной.

Поэтому вам нужно скопировать указатель, возвращаемый config_lookup_string(), в другой массив, если вы хотите использовать его после config_destroy()

person Ingo Leonhardt    schedule 06.05.2015