c++ - 递归使用 TinyXML 生成通用树时出现段错误?

标签 c++ recursion tree tinyxml

我正在尝试使用 TinyXML 解析 XML 文件以构建通用树。我正在尝试递归地执行此操作。问题是,每当我这样做时,我都会遇到段错误。

这是片段:

void buildTree() {
        // Loading XML file and getting rootNode
        string filename = "generalTree.xml";
        TiXmlDocument doc(filename);
        bool loadOkay = doc.LoadFile();
        if (!loadOkay) {
            cout << "Could not load file " << filename << endl;
            cout << "Error='" << doc.ErrorDesc() <<"'. Exiting.\n";
        }
        TiXmlNode* generalTreeNode = doc.FirstChild("GeneralTree");
        TiXmlNode* rootNode = generalTreeNode->FirstChild();
        int key = stoi(rootNode->ToElement()->Attribute("key"));
        Type data = rootNode->ToElement()->GetText();
        root = new TreeNode<Type>("General", key, data);
        // Populating the rest of the tree via recursive function
        recFunction(rootNode);
    }

这里是 recFunction:

  void recFunction(TiXmlNode *node) {
        if(node->FirstChildElement() == NULL) {
            cout << "First child element is null" << endl;
        } else {
            int key = stoi(node->ToElement()->Attribute("key"));
            Type data = node->ToElement()->GetText();
            TreeNode<Type> *treeNode = new TreeNode<Type>("General", key, data);
            cout << "Right BEFORE recursive activates" << endl;
            return recFunction(node->FirstChild());
        }
        cout << "After recursiveness done" << endl;
        // After recursiveness is finished
        while(node->NextSibling() != NULL) {
            if(!node) {
                cout << "Node is null, breaking" << endl;
                break;
            }
            // Converting XML node to TreeNode
            cout << "DOING NODE TO ELEMENT" << endl;
            cout << node->ToText()->Value() << endl;
            cout << "Node is of type: " << typeid(node).name() << endl;
            cout << node->ToElement()->Attribute("key") << endl;
            cout << "DONE WITH NODE TO ELEMENT" << endl;
            int key = stoi(node->ToElement()->Attribute("key"));
            cout << "Key 1 is: " << key << endl;
            Type data = node->ToElement()->GetText();
            cout << "Data 1 is: " << data << endl;
            TreeNode<Type> *prev = new TreeNode<Type>("General", key, data);
            int key2 = stoi(node->NextSibling()->ToElement()->Attribute("key"));
            Type data2 = node->ToElement()->GetText();
            TreeNode<Type> *cur = new TreeNode<Type>("General", key2, data2);
            // Create linked list of siblings
            prev->setSibling(cur);
            node = node->NextSibling();
        }
        cout << "End of while loop reached" << endl;
    }

这是 XML 文件:

<?xml version="1.0"?>
<GeneralTree>
    <Node key="1"> Genres
        <Node key="2">Thriller</Node>
        <Node key="3">Action</Node>
        <Node key="4">Romance
            <Node key="7">A Walk To Remember</Node>
            <Node key="8">The Notebook</Node>
            <Node key="9">Safe Haven</Node>
        </Node>
        <Node key="5">Anime
            <Node key="9">Full Metal Alchemist</Node>
            <Node key="10">Pokemon 2000: The Movie</Node>
        </Node>
    </Node>
    <Node key="12">Genre Sister</Node>
</GeneralTree>

现在,我已将问题隔离到 recFunction 中的以下几行:

    cout << "DOING NODE TO ELEMENT" << endl;
    cout << node->ToText()->Value() << endl;
    cout << "Node is of type: " << typeid(node).name() << endl;
    cout << node->ToElement()->Attribute("key") << endl;
    cout << "DONE WITH NODE TO ELEMENT" << endl;

所以我假设节点在递归函数的某个时刻变为空。问题是我一遍又一遍地查看这个,我似乎无法弄清楚为什么。适当的检查应防止节点变为空。

这是我收到的输出(包括打印语句,以便您可以看到它发生的位置)。

Right BEFORE recursive activates
First child element is null
After recursiveness done
DOING NODE TO ELEMENT
Genres
Node is of type: P9TiXmlNode

提前致谢!

编辑:这是当我运行 gdb 并使用断点时发生的情况

    cout << node->ToText()->Value() << endl;

和 cout << node->ToElement()->Attribute("key") << endl;

Right BEFORE recursive activates
First child element is null
After recursiveness done
DOING NODE TO ELEMENT

Breakpoint 1, GeneralTree<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::recFunction (this=0x100300040, node=0x1003005c0)
    at ./GeneralTree.h:70
70              cout << node->ToText()->Value() << endl;
(gdb) c
Continuing.
Genres
Node is of type: P9TiXmlNode

Breakpoint 2, GeneralTree<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::recFunction (this=0x100300040, node=0x1003005c0)
    at ./GeneralTree.h:72
72              cout << node->ToElement()->Attribute("key") << endl;
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
TiXmlAttributeSet::Find (this=0x60, name=0x100018ede "key") at tinyxml.cpp:1527
1527        for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )

最佳答案

有很多事情,但它们都归结为同一个概念错误。

XML 节点包括文本、空格和属性,而不仅仅是元素。

所以如果你打算递归遍历所有元素,这是错误的:

 return recFunction(node->FirstChild());

应该是这样的:

 return recFunction(node->FirstChildElement());

同样,在您请求 NextSibling 的地方,您可能需要 NextSiblingElement

例如:

int key2 = stoi(node->NextSibling()->ToElement()->Attribute("key"));

如果 NextSibling 返回一个文本节点,则 ToElement 将返回 null。

查看SEGV信息:

TiXmlAttributeSet::Find (this=0x60, name=0x100018ede "key") at tinyxml.cpp:1527

这显示了 0x60 的 this 指针值,这不太可能是有效的。获得这种指针的最可能方法是在空指针的类型转换中进行未经检查的指针调整。 IE。您在某个时候使用了空指针,并且您的代码或库代码已将其强制转换为相关类型。

在这种情况下,由于 node->ToText() 成功,因此 node->ToElement() 必然会返回 null,因为节点是文本节点或元素节点。因此 ToElement 的返回值为 null,对其调用 Attribute 是错误的。

关于c++ - 递归使用 TinyXML 生成通用树时出现段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38190973/

相关文章:

c++ - 单个 makeFile-Windows/Linux/Mac OS

C++ 编译大型结构时内存使用过多

c++ - GLFW 和 Visual Studio Community 2015

sql - SQLite中的递归更新

c++ - 具有指针 C 成员的类 C 的析构函数

c++ - 在切换到 64 位整数之前,为什么使用 INT_MAX 而不是 UINT_MAX?

Python 递归问题 (Leetcode 542)

c++ - 如何避免指针指向 '\0' 之后?

list - Common lisp 树中的最低级别

php - 从数据库表创建数组 "tree"