• 警惕rapidxml的陷阱:添加节点时,请保证变量的生命周期


    项目中要使用xml打包、解析协议,HQ指定了使用rapidxml--号称是最快的xml解析器。

    功能很快完成了,但发现rapidxml为了追求性能,做了一些对用户来说并不友好的设计。下面来说一说:

    给xml对象在添加节点时,不可添加临时变量

    按照一般用法,使用如下方式添加节点:

    rapidxml::xml_document<> doc;
    
    void addNode(std::string value)
    {
       rapidxml::xml_node<>* root = doc.allocate_node(rapidxml::node_element, "unregister_context");
       doc.append_node(root);
    
       root->append_node(doc.allocate_node(rapidxml::node_element, "who_register", value.c_str()));
    }

     但在rapidxml中这么写实有问题的,得这么写:

    rapidxml::xml_document<> doc;
    
    void addNode(std::string value)
    {
       rapidxml::xml_node<>* root = doc.allocate_node(rapidxml::node_element, "unregister_context");
       doc.append_node(root);
    
       root->append_node(doc.allocate_node(rapidxml::node_element, "who_register", doc.allocate_string(value.c_str())));
    }

    看出差别了吗?

    待插入的值"变量value"是作为参数传递进来的,是临时变量。rapidxml为了追求极致性能,在append_node()函数中是直接通过指针来访问value变量的,并没有进行内存拷贝--因此rapidxml在这里提出了一个隐晦的前提条件:在xml对象doc的生命周期内,必须保证"变量value"能够被正常访问。

    那么实际情况呢?

    仔细检查一下,就会发现"变量value"是临时变量,在addNode()函数执行完毕后就会被销毁;此时xml对象rapidxml::xml_document<> doc内部保存的值还指向“变量value”的内存地址,而该地址已经不可用了。因此在访问xml对象时就会发生segment fault。

    问题出现了,该怎么解决?我们是无法控制临时变量的生命周期的,因此只能对该变量进行拷贝。rapidxml已经提供了该功能,这就是allocate_string()函数。该函数在rapidxml对象内部的内存池中为我们的变量申请了一份内存,然后将“变量value”的值拷贝过去;由于是xml对象自己维护该内存池,因此就不存在变量地址失效的问题了。

    以上情况仅针对allocate_node()待插入的值是临时变量这种情况;如果用户能保证待插入变量的生命周期、或者是常量,应该不需要使用allocate_string()函数来分配内存了。例如:

    rapidxml::xml_node<>* root = doc.allocate_node(rapidxml::node_element, "data_coming", "some data");

    这里第三个参数"some data"是常量,生命周期等于整个程序的生命周期,因此就不用再为它分配内存了。

    (ps:此种情况仅是推测,未做测试。)

    在为xml对象添加节点时,请保证变量的生命周期!

    总结:

    rapidxml为了追求性能,减少内存拷贝,就尽可能的通过指针(内存地址)来访问用户的变量;这就对用户提出了要求:必须保证变量的生存周期,如果变量被销毁了,rapidxml就会访问无效的内存地址,引发不可控的后果。

    而对于普通用户来说,一般都比较少注意到这个细节。

    为了追求性能,而牺牲了一定的可用性。这种设计是否合理?

  • 相关阅读:
    印度出差之一
    印度出差疯狂的鸡翅
    GET和POST两种基本请求方法的区别
    对sleep和wait的理解
    Jquery 鼠标滑过时改变元素透明度的动画效果
    记忆里的科比
    New Features Summary Of Sybase® PowerDesigner® 15.0 For Windows[PD15新功能特征摘要]
    WF工作流接口规范
    Foxmail安装文件夹的整体转移(收集)
    c# vs2005 多线程中调用窗体控件 (摘)
  • 原文地址:https://www.cnblogs.com/chutianyao/p/3246592.html
Copyright © 2020-2023  润新知