shared_ptr管理Xerces-c转码资源返回空字符串原因排查
问题根因
你遇到的返回空字符串问题,核心是智能指针生命周期管理错误,另外删除器写法也存在不严谨的地方:
- 直接触发异常的是悬空指针问题
函数内的returned是栈上分配的局部shared_ptr对象,函数执行完返回时,这个局部智能指针会立刻析构,引用计数归零后直接调用删除器释放XMLString::transcode申请的XMLCh内存。你通过return returned.get()拿到的指针,指向的是已经被释放的内存块,属于典型的悬空指针。访问已释放内存本身是C++里的未定义行为,你这边表现为空字符串已经是比较"温和"的结果,换个编译选项或者运行环境直接崩溃都是正常的。 - 删除器写法存在隐性问题
你实现的releaseXMLCh用值传递接收指针参数,形参是原指针的栈上副本:
这段代码虽然能正确释放目标内存(形参的值和原指针一致,指向同一块申请的内存),但void class_name::releaseXMLCh(XMLCh* text) { XMLString::release(&text); }XMLString::release内部会把传入的指针置空,被置空的只是栈上的局部形参,不会修改智能指针持有的原指针,不符合Xerces-c的接口设计预期,虽然不会直接触发你现在的空返回问题,但属于不规范的写法。
正确写法
不要返回裸指针,直接将持有内存的智能指针返回给调用方,让调用方持有智能指针对象,保证XMLCh内存的生命周期覆盖整个使用周期,同时修正参数传递和删除器的问题:
// 1. 返回值改为shared_ptr<XMLCh>,把内存所有权移交给调用方 // 2. 入参改为const std::string&,避免无意义的字符串拷贝 std::shared_ptr<XMLCh> class_name::transcode(const std::string& text) { auto xml_mem = std::shared_ptr<XMLCh>( XMLString::transcode(text.c_str()), // 直接用lambda写删除器,逻辑清晰,也避免单独写静态函数的麻烦 [](XMLCh* p) { XMLString::release(&p); } ); return xml_mem; }
使用时只要持有返回的智能指针对象,内存就不会被提前释放,用完后智能指针超出作用域会自动调用release释放内存,不会泄漏:
// 持有智能指针对象,生命周期覆盖整个XMLCh使用过程 auto transcoded_str = obj.transcode("待转码字符串"); // 需要用裸指针的时候调用get()即可,此时内存是有效的 // 例:DOMElement* root = doc->createElement(transcoded_str.get());
如果你非要返回裸指针,就不能在转码函数内部用智能指针管理内存,必须把内存释放的责任完全交给调用方。但这种写法非常容易出现内存泄漏,不推荐使用。
内容的提问来源于stack exchange,提问作者pscarpati
相关产品推荐
相关产品推荐

