Сбой разбора boost/rapidxml

Мы используем boost/rapidxml для синтаксического анализа XML в реализации брокера публикации/подписки, и для определенной полезной нагрузки XML происходит сбой брокера.

Чтобы исключить как можно больше переменных, я реализовал короткую тестовую программу, выполняющую только синтаксический анализ XML, и сбой аналогичен.

Моя короткая тестовая программа находится здесь:

#include <stdio.h>       // printf
#include <unistd.h>      // read
#include <sys/types.h>   // open
#include <sys/stat.h>    // open
#include <fcntl.h>       // open
#include <errno.h>       // errno
#include <string.h>      // strerror
#include "rapidxml.hpp"
#ifdef LONG_RAPIDXML_NAME_SPACE
// boost version >= 1.45
using namespace boost::property_tree::detail::rapidxml;
#else
// boost version <= 1.44
using namespace rapidxml;
#endif
/* ****************************************************************************
*
* xmlTreePresent -
*/
static void xmlTreePresent(xml_node<>* nodeP, std::string indent, int depth = 0)
{
    static int callNo = 0;
    ++callNo;
    if(nodeP == NULL)
    {
        printf("%sNULL NODE\n", indent.c_str());
    }
    char* name  = nodeP->name();
    char* value = nodeP->value();
    printf("%s%s (%s) (call %d, depth %d)\n", indent.c_str(), name, value, callNo, depth);
    xml_node<>* child = nodeP->first_node();
    while(child != NULL)
    {
        printf("%schild at         %p\n", indent.c_str(), child);
        printf("%schild->name() at %p\n", indent.c_str(), child->name());
        if((child->name() != NULL) && (child->name()[0] != 0))
        {
            xmlTreePresent(child, indent + "  ", depth + 1);
        }
        child = child->next_sibling();
    }
}
/* ****************************************************************************
*
* xmlDocPrepare -
*/
static xml_node<>* xmlDocPrepare(char* xml)
{
    xml_document<> doc;
    try
    {
        doc.parse<0>(xml);
    }
    catch(parse_error& e)
    {
        printf("PARSE ERROR: %s\n", e.what());
        return NULL;
    }
    catch(...)
    {
        printf("GENERIC ERROR during doc.parse\n");
        return NULL;
    }
    xml_node<>* father = doc.first_node();
    return father;
}
/* ****************************************************************************
*
* main -
*/
int main(int argC, char* argV[])
{
    char* fileName = argV[1];
    int   fd;
    if((fd = open(fileName, O_RDONLY)) == -1)
    {
        printf("open('%s'): %s", fileName, strerror(errno));
        exit(1);
    }
    struct stat  statBuf;
    if(stat(fileName, &statBuf) != 0)
    {
        printf("stat('%s'): %s", fileName, strerror(errno));
        exit(2);
    }
    char* buf = (char*) calloc(1, statBuf.st_size + 1);
    if(buf == NULL)
    {
        printf("calloc(%lu): %s", statBuf.st_size + 1, strerror(errno));
        exit(3);
    }
    int nb = read(fd, buf, statBuf.st_size);
    if(nb == -1)
    {
        printf("read('%s'): %s", fileName, strerror(errno));
        exit(4);
    }
    else if(nb != statBuf.st_size)
    {
        printf("read %d characters, wanted %lu", nb, statBuf.st_size);
        exit(5);
    }
    xml_node<>*   father    = xmlDocPrepare((char*) buf);
    xmlTreePresent(father, "");
    return 0;
}

Пример входного XML находится здесь: http://pastebin.com/rYiDjP7E.

Я пробовал как в Ubuntu (libboost_serialization.so.1.49.0), так и в CentOS (libboost_serialization.so.5), и я получаю аналогичные сбои.

[ Я не уверен, но думаю, что дерево свойств boost находится в библиотеке сериализации... ]

В CentOS это происходит немного дальше, но заканчивается аналогичным сбоем.

Более чем благодарен за помощь, у нас есть пользователи, ожидающие исправления ...


person kzangeli    schedule 28.04.2014    source источник


Ответы (1)


Прежде всего.

  1. >OMG‹ У вас там довольно беспорядочный код — извините за прямоту, возможно.
  2. Это не С++! Замените весь main на

    int main(int argc, char* argv[])
    {
        std::ifstream ifs(argc>1? argv[1] : "input.txt");
        std::string buf(std::istreambuf_iterator<char>(ifs), {});
    
        xml_node<>* father = xmlDocPrepare(&buf[0]);
        xmlTreePresent(father, "");
    }
    
  3. Rapidxml не является частью Boost. Он используется (деталь реализации) в дереве свойств Boost.

  4. Boost Property Tree — это собственная библиотека, не связанная с Boost Serialization (это означает, что вам также не нужно ссылаться на общую библиотеку)

Настоящий баг здесь:

static xml_node<>* xmlDocPrepare(char* xml)
{
    xml_document<> doc;

    ..
    xml_node<>* father = doc.first_node();
    return father;
}

Это возвращает ссылку на (в) локальный объект, но локальный (doc) не существует за пределами оператора return! Я бы исправил этот экземпляр следующим образом:

int main(int argc, char* argv[])
{
    std::ifstream ifs(argc>1? argv[1] : "input.txt");
    std::string xml(std::istreambuf_iterator<char>(ifs), {});

    try
    {
        xml_document<> doc;
        doc.parse<0>(&xml[0]);
        xmlTreePresent(doc.first_node());

        return 0;
    }
    catch(parse_error& e) { printf("PARSE ERROR: %s\n", e.what()); }
    catch(...)            { printf("GENERIC ERROR during doc.parse\n"); }
    return 1;
}

Обратите внимание, как я уменьшил 76 строк кода до 17 :) И утекает меньше памяти.

Обновление Вот полностью очищенная версия на - УРА - C++, а не C: посмотреть Live On Coliru, где он анализирует образец XML, но с удаленными игнорируемыми пробелами, чтобы вы могли лучше видеть результат.

Конечно, он работает и с «красивым» xml.

#include <fstream>
#include <iostream>
#include <iomanip>
#include <boost/property_tree/detail/rapidxml.hpp>

using namespace boost::property_tree::detail::rapidxml;

static void xmlTreePresent(xml_node<> const* nodeP, int depth = 0)
{
    static int callNo = 0;
    callNo += 1;
    if(nodeP)
    {
        std::cout << std::setw(depth*2) << "" << nodeP->name()/* << " (" << nodeP->value() << ") (call " << callNo << ", depth " << depth << ")" */ << "\n";
        for (xml_node<>* child = nodeP->first_node(); child; child = child->next_sibling())
        {
            auto name = child->name();
            if(name && name[0])
            {
                xmlTreePresent(child, depth + 1);
            }
        }
    } else
    {
        std::cout << std::setw(depth*2) << "" << "NULL NODE\n";
    }
}

int main(int argc, char* argv[])
{
    std::ifstream ifs(argc>1? argv[1] : "input.txt");
    std::string xml(std::istreambuf_iterator<char>(ifs), {});

    try
    {
        xml_document<> doc;
        doc.parse<0>(&xml[0]);
        xmlTreePresent(doc.first_node());

        return 0;
    }
    catch(parse_error& e) { printf("PARSE ERROR: %s\n", e.what()); }
    catch(...)            { printf("GENERIC ERROR during doc.parse\n"); }
    return 1;
}

Вот вывод с удаленной отладочной информацией (как показано в /комментарии/):

updateContextRequest
contextElementList
    contextElement
    entityId
        id
    contextAttributeList
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
    contextElement
    entityId
        id
    contextAttributeList
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
    contextElement
    entityId
        id
    contextAttributeList
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
    contextElement
    entityId
        id
    contextAttributeList
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
    contextElement
    entityId
        id
    contextAttributeList
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
        contextAttribute
        name
        type
        contextValue
        metadata
            contextMetadata
            name
            type
            value
updateAction
person sehe    schedule 28.04.2014
comment
Обновите, теперь я почистил всю программу, и теперь ~40 строк кода, < b>Жить на Колиру. (Надеюсь, это помогло и станет уроком: пишите на C++, а не на C. Это более продуктивно и менее подвержено ошибкам.) - person sehe; 29.04.2014
comment
На самом деле я просто сократил его до ~25 строк. Это не пройдет проверку кода со мной, но показывает, что это всего лишь 3 функции из ~ 5 строк. - person sehe; 29.04.2014
comment
Спасибо, сехе, за быстрый ответ. Я переместил часть xmlDocPrepare (особенно переменную xml_document‹› doc) в процедуру синтаксического анализа, и все работает просто отлично. Насчет C или C++, ну это вопрос мнения. Я сам предпочитаю C. Еще раз спасибо! - person kzangeli; 29.04.2014
comment
@kzangeli Хорошо, справедливо. Мы можем не согласиться, но да, вкус тоже имеет значение (иначе кто-то поправит меня, говоря, что используйте Python, используйте Haskell и т. д. :)) - person sehe; 29.04.2014