2

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.

3
  • Try not to use global std::list? Use a member variable instead to test if your logic is all working. Commented Sep 15, 2017 at 20:23
  • Not sure how to do this. Totally new to c++ :) Commented Sep 15, 2017 at 21:25
  • Put std::list<pugi::xml_node> packages into your Packages class, it will become a member. Commented Sep 15, 2017 at 23:28

1 Answer 1

0

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.