Как исправить проблемы с владением RapidXML String?
RapidXML - это быстрый и легкий C++ XML DOM Parser, но он имеет некоторые особенности.
Худшее из них, на мой взгляд, таково:
3.2 Право собственности на строки.
Узлам и атрибутам, созданным RapidXml, не принадлежат их строки имени и значения. Они просто держат указатели на них. Это означает, что вы должны быть осторожны при установке этих значений вручную, используя
xml_base::name(const Ch *)
или жеxml_base::value(const Ch *)
функции.Необходимо позаботиться о том, чтобы время жизни передаваемой строки было, по крайней мере, таким же, как время жизни узла / атрибута. Самый простой способ добиться этого - выделить строку из memory_pool, принадлежащую документу. использование
memory_pool::allocate_string()
функция для этой цели.
Теперь я понимаю, что так сделано для скорости, но это похоже на автомобильную аварию, ожидающую своего появления. Следующий код выглядит безобидным, но "name" и "value" выходят из области видимости, когда возвращается foo, поэтому документ не определен.
void foo()
{
char name[]="Name";
char value[]="Value";
doc.append_node(doc.allocate_node(node_element, name, value));
}
Предложение об использовании allocate_string()
согласно ручным работам, но это так легко забыть.
Кто-нибудь "улучшил" RapidXML, чтобы избежать этой проблемы?
1 ответ
Я не использую RapidXML, но, возможно, мой подход может решить вашу проблему.
Я начал использовать Xerces, но я обнаружил, что он тяжел, помимо других мелких неприятностей, поэтому я перешел в CPPDOM. Когда я сделал этот шаг, я решил создать набор классов-оболочек, чтобы мой код не зависел от конкретного "движка" XML, и я мог при необходимости портировать на другой.
Я создал свои собственные классы для представления базовых объектов DOM (узел, документ и т. Д.). Эти классы внутренне используют идиому pimpl для использования объектов CPPDOM. Поскольку мой объект узла содержит "реальный" объект узла (из CPPDOM), я могу управлять чем угодно, поэтому правильное размещение и освобождение строк не будет проблемой там.
Поскольку мой код предназначен для CPPDOM, я не думаю, что он будет для вас очень полезным, но я могу опубликовать его, если хотите.
Кстати, если у вас уже есть слишком много кода, который уже использует RapidXML, вы можете воспроизвести его интерфейсы в ваших классах-оболочках. Я этого не делал, потому что код, который использовал Xerces, был не таким длинным, и мне все равно пришлось бы его переписать.