Reading a list of xml nodes causes segmentation fault

446 Views Asked by At

I try to develop a package system for a game server engine i use, so, upon start i read a XML file and add the nodes to a list so i can use later. I can read the list after i created it, in same method. But when i try to read it from another file, it will give me segmentation fault. Lets see some code.

First, I have added a packages.cpp and packages.h. They look like:

packages.cpp

#include "otpch.h"
#include "packages.h"
#include "pugicast.h"
#include "tools.h"
#include "events.h"

std::list<pugi::xml_node> packages;

Packages::Packages()
{
    //
}

bool Packages::loadFromXml()
{
    std::string packagesPath = "data/packages";
    pugi::xml_document packagesDoc;
    pugi::xml_parse_result packagesResult = packagesDoc.load_file((packagesPath + std::string("/packages.xml")).c_str());
    if (!packagesResult) {
        printXMLError("Error - BaseEvents::loadFromXml", "data/packages/packages.xml", packagesResult);
        return false;
    }

    for (auto packageNode : packagesDoc.child("packages").children()) {
        packages.push_back(packageNode);
    }

    // I can read the list here without any problem.

    return true;
}

packages.h:

extern std::list<pugi::xml_node> packages;

class Packages
{
    public:
        Packages();
        bool loadFromXml();
};

Then I add this code to the startup file

Packages g_packages;

void mainLoader()
{
    std::cout << ">> Loading packages" << std::endl;
    if (!g_packages.loadFromXml()) {
        startupErrorMessage("Unable to load packages!");
        return;
    }
}

And finally, I try to iterate this list like this in another file:

#include "packages.h"

bool Events::loadFromPackages()
{
    for (auto& package : packages) {
        std::cout << package.name() << std::endl; // segmentation fault
    }
}

Thankful for any help.

1

There are 1 best solutions below

0
On

Moving pugi::xml_document packagesDoc; to global scope will probably solve this issue.

When pugi::xml_document goes out of scope and is destroyed, all xml_node objects associated with nodes from that document become invalid. This is similar to iterators in STL containers - you can get iterators to std::list elements, but destroying the list object means that you can't access them.

It is likely that a better solution is to use something other than globals here - for example, maybe putting both xml_document and std::list<xml_node> inside the Packages class is a better option, but this somewhat depends on the structure you want your code to have.