2012-09-04 98 views
0

我以一種非常糟糕的方式使用rapidXML獲取配置文件的值。RapidXML NULL指針

xml_document<> doc; 
doc.parse<parse_full>(buffer); 
int a = atoi(doc.first_node("master")->first_node("profile")->first_node("width")->value()); 

如果節點不存在「first_node」返回0,所以「 - > value()」崩潰。返回一個新的xml_node將會修復崩潰,但是內存泄漏又如何呢?

這是rapidXML的fonction與新老而歸:

xml_node<Ch> *first_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const 
    { 
     if (name) 
     { 
      if (name_size == 0) 
       name_size = internal::measure(name); 
      for (xml_node<Ch> *child = m_first_node; child; child = child->next_sibling()) 
       if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive)) 
        return child; 
      return new xml_node<Ch>(node_document); 
      //return 0; 
     } 
     else 
      return m_first_node; 
    } 
+0

您應該檢查鏈中的每個節點,而不是將庫更改爲返回新的空節點。這將_will_創建內存泄漏。 –

+0

我不想檢查每個節點到達下一個之前存在。我希望能夠縮短如下行:doc.first_node(「master/profile/width」).value()而不檢查是否有空指針。你覺得這更友好嗎?另外,我如何避免內存泄漏。新創建的元素如何自動銷燬? – Naster

+0

爲避免內存泄漏,您應該查看[智能指針](http://en.cppreference.com/w/cpp/memory)。 –

回答

0

你應該使用異常,如:

int a; 
try 
{ 
    xml_document<> doc; 
    doc.parse<parse_full>(buffer); 
    a = atoi(doc.first_node("master")->first_node("profile")->first_node("width")->value()); 
} 
catch(NodeNotExists &ex) 
{ 
    // process error condition 
} 

另外,如果不想改變rapidxml代碼,使用包裝功能,如:

template<typename T> 
T* notnull(T* arg) 
{ 
    if (arg == 0) 
     throw NodeNotExists(); 
    return arg; 
} 
0

擴展仇恨引擎的答案,我創建了一類靜態幫助函數通過包裝節點值訪問來處理這種情況。通過here查看我的答案。你可以擴展或者沿着xpath風格的節點訪問(我不相信目前內置於RapidXML,但是others do)的路線追求更多東西。

編輯:您可以創建一個包裝函數,需要一個簡單的類似XPath的路徑和結合起來,與我的包裝的一個獲得類似...

int a = GetNodeInt(GetFirstNodePath(doc, "master/profile/width"), 0); 

凡GetNodeInt和GetFirstNodePath定義的東西像這樣...

int GetNodeInt(rapidxml::xml_base<>* node, int DefaultValue) 
    { 
     int temp; 
     try 
     { 
      if (node == 0) return DefaultValue; 
      if (sscanf(node->value(), "%d", &temp) != 1) return DefaultValue; 
      return temp; 
     } 
     catch (...) { return DefaultValue; } 
    } 

    // Find node with simple path from current node such as "first/second/third" 
    rapidxml::xml_node<>* GetFirstNodePath(rapidxml::xml_node<>* root, const char *path) 
    { 
     xml_node<>* node = root; 
     char* last = (char*)path; // only using this pointer to read 
     char* cur = last; 
     if (cur == 0 || root == 0) return 0; 
     while (node) 
     { 
      if (*cur == '/' || *cur == 0) 
      { 
       if (cur != last) node = node->first_node(last,cur-last); 
       if (*cur == 0) break; 
       last = cur + 1; 
      } 
      ++cur; 
     } 
     return node; 
    } 

現在這段代碼還沒有經過徹底測試,但給你的一般想法。