Получить значение ошибки с помощью синтаксического анализатора libxml2

Я пытаюсь проанализировать XML-файл с помощью саксофонного интерфейса libxml2. Иногда это прекрасно работает, но затем я изменяю порядок двух строк в xml (он остается действительным для coure) и некоторые значения становятся недействительными после разбора. Я использую startElementNsSAX2Func для startElement, у него есть аргумент const xmlChar ** attribute, который хранит атрибуты текущего элемента.

В начале моего метода startElement я создаю простой объект для обработки атрибутов
Вот код класса:

class XMLElementAttributes {
public:
static const int AttributeArrayWidth = 5;
static const int LocalNameIndex = 0;
static const int PrefixIndex = 1;
static const int URIIndex = 2;
static const int ValueIndex = 3;
static const int EndIndex = 4;

XMLElementAttributes( int nb_attributes, const xmlChar **attributes) :
nb_attributes(nb_attributes),
attributes(attributes){
}

xmlChar* getLocalName( int index ) const {
return (xmlChar*)attributes[ AttributeArrayWidth * index + LocalNameIndex];
}

xmlChar* getValue( int index ) const{
return (xmlChar*)std::string(attributes[ AttributeArrayWidth * index + ValueIndex],attributes[ AttributeArrayWidth * index + EndIndex]).c_str();
}

int getLength() const{
return nb_attributes;
}

private:
int nb_attributes;
const xmlChar ** attributes;
};

(xmlChar — это Typedef без знака char xmlChar)

Затем, если мне нужно сохранить значение атрибута, я клонирую его с помощью этого метода staic (я также попытался использовать xmlStrdup в libxml2, результат тот же):

xmlChar* cloneXMLString(const xmlChar* const source) {
xmlChar* result;
int len=0;
std::cout<<"source"<<std::endl;
while (source[len] != '\0'){
std::cout<<(void*)&source[len] << ": " << source[len] <<std::endl;
len++;
}
std::cout<<std::endl;
std::cout<<"result, "<<std::endl;
result = new xmlChar[len+1];
for (int i=0; i<len; i++){
result[i] = source[i];
std::cout<<(void *)&source[i] << ": "<< source[i] << std::endl;
}
std::cout<<std::endl;
result[len] = '\0';
return result;
}

Это работает на 99%, но иногда результат в конце не содержит ничего похожего на источник. Вот пример выходных данных (ввод abcdef и \ 0 завершен):

source
0x7fdb7402cde8: a
0x7fdb7402cde9: b
0x7fdb7402cdea: c
0x7fdb7402cdeb: d
0x7fdb7402cdec: e
0x7fdb7402cded: fresult,
0x7fdb7402cde8: !
0x7fdb7402cde9:
0x7fdb7402cdea:
0x7fdb7402cdeb:
0x7fdb7402cdec: x
0x7fdb7402cded:

Я называю это так:

xmlChar* value = cloneXMLString(attributes.getValue(index));

Таким образом, хотя адрес источника не изменился, его значение изменилось. Разбор файла xml продолжается без каких-либо проблем, следующие значения после клонирования снова становятся действительными.

Ошибка всегда в том же элементе и аргументе, если файл XML не изменился. Если я изменю что-то немного в XML, например:

<somenodes a="arg1" b="arg2">
<node c="abc" d="def" />
<node c="ghi" d="jkl" />
</somenodes>

в

<somenodes a="arg1" b="arg2">
<node c="ghi" d="jkl" />
<node c="abc" d="def" />
</somenodes>

ошибка появляется где-то еще или исчезает и синтаксический анализ работает нормально. Что может вызвать это?

Редактировать:

Мой метод начального элемента:

void MyParser::startElement( void * ctx,
const xmlChar * localName,
const xmlChar * prefix,
const xmlChar * URI,
int nb_namespaces,
const xmlChar ** namespaces,
int nb_attributes,
int nb_defaulted,
const xmlChar ** attrs ){

XMLElementAttributes attributes ( nb_attributes, attrs );

switch ( state ) {
case Somestate:
if ( xmlStrcmp( localName, StrN("SomeName").xmlCharForm() ) == 0) {
someVar = new SomeObject(attributes);
}
break;

...

}
}

StrN создает xmlChar из char *. someVar — это статическое поле в классе MyParser (startElement также является статическим). В конструкторе SomeObject я пытаюсь получить значения атрибутов следующим образом:

class SomeObject {
public:
SomeObject( XMLElementAttributes &attributes){
for (int i=0; i< attributes.getLength(); i++) {
xmlChar* name = attributes.getLocalName(i);
if ( xmlStrcmp( name, StrN("somename").xmlCharForm()) == 0 ) {
somename = cloneXMLString(attributes.getValue(i));
}
...
}
}
};

1

Решение

Понятно, что источник не указывает на правильную память. Это может быть из-за того, что память уже была освобождена, или из-за того, что она указывала на память стека, объявленную в функции, которая уже была завершена.

Такая память может быть перезаписана непредсказуемым образом, что вы видите здесь.

Нужно было бы увидеть больше контекста, особенно, как вы звоните cloneXMLString и откуда берется память, передаваемая этой функции, для более подробного ответа.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]