2016-07-04 11 views
1

Я пытаюсь разобрать XML-файл с помощью TinyXML, чтобы построить общее дерево. Я пытаюсь сделать это рекурсивно. Проблема в том, что я получаю ошибку сегментации всякий раз, когда я это делаю.Ошибка сегментации при рекурсивном использовании TinyXML для генерации общего дерева?

Вот фрагмент кода:

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 

Заранее благодарен!

EDIT: вот что происходит, когда я отлаживать и использовать контрольную точку в

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

и соиЬ < < node-> ToElement() -> Атрибут ("ключ") < < 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) 
+2

Попробуйте выполнить свой код с помощью отладчика. –

+0

@ IvanRubinson Я пробовал. Проблема в том, что мой отладчик не работает :(Планирование решения этого сразу после того, как я это выясню. – ProjectProgramAMark

+2

Вы не можете программировать без отладчика. Исправьте это в первую очередь. –

ответ

0

Есть много вещей, но все они сводятся к одной и той же концептуальной ошибке.

Узлы XML включают текст, пробелы и атрибуты, а не только элементы.

Так что если вы намерены рекурсию по всем элементам, это неправильно:

return recFunction(node->FirstChild()); 

Вместо этого он должен быть таким:

return recFunction(node->FirstChildElement()); 

Аналогично, когда вы просите NextSibling вы, вероятно, хотите NextSiblingElement.

Например:

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

Если NextSibling возвращает текстовый узел, то ToElement возвратит нуль.

Глядя на информацию SEGV:

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

Это показывает значение this указатель 0x60, который вряд ли будет действительным. Наиболее вероятным способом получения такого указателя является неконтролируемая корректировка указателя в типе, отличном от нулевого указателя. То естьвы в какой-то момент использовали нулевой указатель, и ваш код или библиотечный код передал его соответствующему типу.

В этом случае с node->ToText() преуспел, то node->ToElement() обязан возвращать null, поскольку узел является либо текстовым узлом, либо узлом элемента. Поэтому возвращаемое значение ToElement равно null, и при вызове Attribute это ошибка.

+0

Спасибо за помощь! – ProjectProgramAMark