Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: OdkoОтветов: 2

Моя программа читает файл конфигурации, используя 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)

cstructheapvalgrindlibconfig

Ответы

Ответ 1 · рейтинг 2 · mshildt

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 */

Ответ 2 · рейтинг 3 · Ingo Leonhardt

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

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

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы