c++segmentation-faultrapidxml

c++ rapidxml cant use saved xml_document properly


i'm trying to parse some xml string to an xml_document, and save the xml_document to a variable for further usage. Directly after the parsing the xml_document is useable, but i cant access it from another method.

Heres the example code: XML.h

//
// Created by artur on 18.07.18.
//

#ifndef PLSMONITOR_XML_H
#define PLSMONITOR_XML_H
#include <rapidxml/rapidxml.hpp>

class XML {

public:
    XML();
    void print();

private:
    rapidxml::xml_document<> _store_xml;

};

#endif //PLSMONITOR_XML_H

XML.cpp

//
// Created by artur on 18.07.18.
//

#include "XML.h"
#include <string>
#include <cstring>
#include <iostream>

using namespace std;
XML::XML() {
    std::string str{"<Store>"
                           " <Field1>1</Field1>"
                           "</Store>"
                           ""};
    char* cstr = new char[str.size() + 1];
    strcpy (cstr, str.c_str());
    _store_xml.parse<0>(cstr);
    // this prints the 1
    cout <<_store_xml.first_node("Store")->first_node("Field1")->value() << endl;
    delete [] cstr;

}

void XML::print() {
    // this exits with Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
    cout <<_store_xml.first_node("Store")->first_node("Field1")->value() << endl;

}

int main(int argc, char *argv[]) {
    cout << "Test of XML" << endl;
    XML xml{};
    xml.print();
}

Using the xml_document in the constructor is fine, but using it in the print method will crash. This is the console output:

Test of XML 1

Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

Anybody got an idea how to properly use the rapidxml document and save the xml struct for further use?

Thanks


Solution

  • The problem is that you are violating contract of xml_document::parse method by disposing of the xml string before disposing of the document, as stated in the documentation

    The string must persist for the lifetime of the document.

    xml_document does not copy string content to avoid extra memory allocations and therefore string must be kept alive. You can probably make string a class field. Also note that with C++17 there is a non-const-qualified data method in string class so there is no need to allocate another temporary buffer.