3

I am facing an issue where I have a configuration file and I parse it with boost::property_tree:info_parser.

I use this code to do the work:

struct _Config
{
    std::string info[2];
    boost::property_tree::ptree pt;
    _Config()
    {
        //check if config file exists, if not create it, etc, do other stuff not related to the issue
        //this code reproduces the issue
        //DEFAULT VALUE, can be changed by configuration later
        info[0] = "If updating this file make sure to update all settings accordingly.";
        info[1] = "This program has been created by Name 'Nickname' Lastname";
    }
    void Save()
    {
        boost::property_tree::info_parser::write_info(".\\config.cfg", pt);
    }
    void Load()
    {
        boost::property_tree::info_parser::read_info(".\\config.cfg", pt);
        {
            //check if variable already exists in config file, if yes load it to
            {
                //try to load entry
                boost::optional<std::string> v = pt.get_optional<std::string>("Info.a");
                if (v.is_initialized())
                    //overwrite default value
                    info[0] = v.get();
            }
            //if entry does not exist it will be created now, else the loaded value will be saved
            pt.put<std::string>("Info.a", info[0]);
        }
        //again for next variable
        {
            {
                boost::optional<std::string> v = pt.get_optional<std::string>("Info.b");
                if (v.is_initialized())
                    info[1] = v.get();
            }
            pt.put<std::string>("Info.b", info[1]);
        }
        Save();
    }
    ~_Config()
    {
        Save();
        pt.clear();
    }
} Config;

Now,my section does look the first time like this:

Info
{
    a "If updating this file make sure to update all settings accordingly."
    b "This program has been created by Name 'Nickname' Lastname"
}

when starting again my configuration becomes this when saving:

Info
{
    a If updating this file make sure to update all settings accordingly.
    b This program has been created by Name 'Nickname' Lastname
}

but after relaunching the code again, the info section becomes a mess and my program breaks:

Info
{
    a If
    updating this
    file make
    sure to
    update all
    accordingly. ""
    b This
    program has
    been created
    by Name
    'Nickname' Lastname
}

How do I make sure that spaces are an accepted character and the quotes are not removed? I also noticed that any comments I make in the config file are not being saved, is there an option to save them?

I am using boost 1.55 with Visual Studio 2013 on Windows 8 x64 in a 32bit application.

Gizmo
  • 1,990
  • 1
  • 24
  • 50
  • If you want it interpreted as one string, maybe putting quotes around it will do ? "\"If updating this file make sure to update all settings accordingly.\""; – Kiroxas May 15 '14 at 14:58
  • 1
    I initially Did put quotes, but the info parser removes them? – Gizmo May 15 '14 at 15:08
  • This will modify the string itself so when displaying info[0] I would need to strip the quotes first? (and watch out not to strip real quoted that are intended?) – Gizmo May 15 '14 at 16:27
  • Oh: _"INFO round-trips except for the loss of comments and include directives."_ **[docs](http://www.boost.org/doc/libs/1_55_0/doc/html/boost_propertytree/parsers.html#boost_propertytree.parsers.info_parser)** – sehe May 15 '14 at 23:55

1 Answers1

4

It was Undefined Behaviour, specifically

The static initialization fiasco

The manifestation here is quite subtle!

Valgrind told me that info_parser::is_simple_data<char> is accessing a string freed. That string would be the local static. Both are being called from __run_exit_handlers() but not in any particular order! See the linked C++FAQ entry for explanations.

Solution, don't depend on global statics with RAII:

int main()
{
    _Config Config;
    Config.Load();
}

is just fine, see it Live On Coliru

sehe
  • 374,641
  • 47
  • 450
  • 633
  • Is that a local static inside the Boost code? So it's still a Boost bug? – Lightness Races in Orbit May 15 '14 at 23:30
  • @LightnessRacesinOrbit You might say so. I must say, the local static seems fine, to me, as long as the documentation mentions that the use of the library function(s) is restricted to within `main()`... I haven't found that warning (yet) – sehe May 15 '14 at 23:31
  • It also makes the function non-reentrant. I'd avoid if I were them. – Lightness Races in Orbit May 15 '14 at 23:32
  • @LightnessRacesinOrbit it doesn't, because it is an immutable constant (yes, that' a bit ironic, since this bug hinged on the "immutable constant" being destructed, but oh well) – sehe May 15 '14 at 23:32