1

I'm using libconfig.h to read parameters from a configuration file, but I've problems printing values inside/outside a function.

example.h

int get_config();

example.c

#include <stdio.h>
#include <stdlib.h>
#include <libconfig.h>
#include "example.h"

typedef struct Conf{
    int myInt;
    const char *myString;
}Conf;

#define CONFIGFILE "./my.conf"
Conf *config;


int get_config(){
    config_t cfg;
    config_init(&cfg);

    if (!config_read_file(&cfg, CONFIGFILE)) {
        fprintf(stderr, "%s:%d - %s\n",
            config_error_file(&cfg),
            config_error_line(&cfg),
            config_error_text(&cfg));
        config_destroy(&cfg);
        return(EXIT_FAILURE);
    }

    if(config_lookup_int(&cfg,"myInt", &config->myInt)){
        printf("myInt = %d\n", config->myInt);
    }

    if(config_lookup_string(&cfg,"myString", &config->myString)){
        printf("myString = %s\n", config->myString);
    }

    config_destroy(&cfg);
    return 0;
}

int main(){
    config = (Conf*) malloc(sizeof(Conf));
    if(get_config() == EXIT_FAILURE){
        return 0;
    }
    get_config();

    printf("myInt = %d\n",config->myInt);
    printf("myString = %s\n",config->myString);

    return 0;
}

The value of myInt printed inside/outside get_config() is the same. For myString, the call in main() return spurious chars, different from what printed before.

What's wrong?

timrau
  • 22,578
  • 4
  • 51
  • 64

1 Answers1

1

From the libconfig 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.

Your config_t cfg is local to get_config and goes out of scope after leaving that function. That means (a) that you can't clean up cfg properly with config_destroy() later and (b) that any references inside cfg might not be accessible, because the stack space has been overwritten.

You can make a copy of the string with strdup in get_config. In that case, destroy cfg at the end of get_config, just as you'd fclose any open local files. Also take care to free your string later.

Another approach is to make cfg local to main and keep it alive during the execution time of the program. Pass &cfg to get_config as a pointer and destroy cfg before returning from main. In that case, the string will be valid as long as cfg is valid.

M Oehm
  • 28,726
  • 3
  • 31
  • 42
  • Pardon me, I leave out the `config_destroy()` but it's not that the problem. Running it, I get values inside the function (Ok), but in main only the int value is right. The string show me spurious chars (eg. �e4). – user4129093 Oct 16 '14 at 11:12
  • My answer addresses this question: Your string, i.e. the memory needed to hold it, doesn't "stay alive" long enough. You either must make a copy (and don't care when the original string "dies") or make your `cfg`, which owns the original string, live long enough by making `cfg` a variable in `main`. – M Oehm Oct 16 '14 at 11:17
  • The string is stored as a pointer in `Conf`. When what it points to is no longer valid, the pointer is useless. That's what happens in your case. (Well, that's what _probably_ happens; I haven't tried it out, because I didn't want to install `libconfig`.) The `int` doesn't have that problem. – M Oehm Oct 16 '14 at 11:19
  • Thank you! Now it run, leaving my string alive :) Is `libconfig` a good solution? something "better"? – user4129093 Oct 16 '14 at 11:44
  • I have no experience with `libconfig`, but from what I've seen it looks good to me. Better than rolling your own. The problem of pointers to char arrays going stale isn't a problem of `libconfig`, but of C. Be prepared to deal with it more often. – M Oehm Oct 16 '14 at 12:00