AVRO C++编码字符串时API崩溃问题求助
AVRO C++ 字符串编码崩溃问题
我是编程和AVRO的新手,尝试对字符串进行AVRO编码解码,完全按照Apache AVRO C++官方文档示例操作。
JSON Schema
{ "type": "record", "name": "cpx", "fields" : [ {"name": "re", "type": "string"}, {"name": "im", "type" : "string"} ] }
生成的头文件(bla.hh)
namespace c { struct cpx { std::string re; std::string im; cpx() : re(std::string()), im(std::string()) { } }; } namespace avro { template<> struct codec_traits<c::cpx> { static void encode(Encoder& e, const c::cpx& v) { avro::encode(e, v.re); avro::encode(e, v.im); } static void decode(Decoder& d, c::cpx& v) { if (avro::ResolvingDecoder *rd = dynamic_cast<avro::ResolvingDecoder *>(&d)) { const std::vector<size_t> fo = rd->fieldOrder(); for (std::vector<size_t>::const_iterator it = fo.begin(); it != fo.end(); ++it) { switch (*it) { case 0: avro::decode(d, v.re); break; case 1: avro::decode(d, v.im); break; default: break; } } } else { avro::decode(d, v.re); avro::decode(d, v.im); } } }; }
CPP源码文件(test.cpp)
#include <stdlib.h> #include "bla.hh" #include "avro/Encoder.hh" #include "avro/Decoder.hh" int main() { std::unique_ptr<avro::OutputStream> out = avro::memoryOutputStream(); avro::EncoderPtr e = avro::binaryEncoder(); e->init(*out); c::cpx c1; c1.re = "hello"; c1.im = "thanks"; avro::encode(*e, c1); std::unique_ptr<avro::InputStream> in = avro::memoryInputStream(*out); avro::DecoderPtr d = avro::binaryDecoder(); d->init(*in); c::cpx c2; avro::decode(*d, c2); std::cout << '(' << c2.re << ", " << c2.im << ')' << std::endl; std::cout << "DECODED" << std::endl; return 0; }
编译命令
g++ test.cpp -std=c++11 -lavrocpp
崩溃信息
运行程序触发段错误,核心转储的GDB回溯如下:
#0 __memcpy_ssse3_back () at ../sysdeps/x86_64/multiarch/memcpy-ssse3-back.S:896 #1 0x00007f28e9dad9e1 in avro::BinaryEncoder::encodeString(std::string const&) () from /usr/local/lib/libavrocpp.so.1.11.0 #2 0x0000000000401778 in avro::codec_traits<std::__cxx11::basic_string<char, std::char_traits, std::allocator > >::encode(avro::Encoder&, std::__cxx11::basic_string<char, std::char_traits, std::allocator > const&) () #3 0x0000000000401a6e in void avro::encode<std::__cxx11::basic_string<char, std::char_traits, std::allocator > >(avro::Encoder&, std::__cxx11::basic_string<char, std::char_traits, std::allocator > const&) () #4 0x0000000000401830 in avro::codec_traits<c::cpx>::encode(avro::Encoder&, c::cpx const&) () #5 0x0000000000401ddc in void avro::encode<c::cpx>(avro::Encoder&, c::cpx const&) () #6 0x00000000004014ac in main ()
问题原因
从回溯看,崩溃发生在avro::BinaryEncoder::encodeString调用memcpy时,核心原因是C++标准库ABI不兼容:
- 程序用
-std=c++11编译,启用了GCC的__cxx11版本std::string(C++11引入的新实现); - 系统中安装的
libavrocpp.so.1.11.0可能是用旧标准(如C++03)或不同ABI编译的,导致AVRO库期望的std::string与程序中的std::string内存布局不一致,触发非法内存访问。
另外,编码完成后未调用e->flush(),虽不直接导致崩溃,但可能造成输出流数据不完整,引发后续解码问题。
解决方法
统一C++标准库ABI
编译程序时添加-D_GLIBCXX_USE_CXX11_ABI=0,强制使用旧ABI匹配AVRO库:g++ test.cpp -std=c++11 -D_GLIBCXX_USE_CXX11_ABI=0 -lavrocpp或者重新编译AVRO库,使用
-std=c++11启用新ABI,确保和程序编译选项一致。添加编码器刷新操作
在avro::encode(*e, c1);后添加e->flush();,确保所有数据写入输出流:avro::encode(*e, c1); e->flush(); // 新增该行编译时添加调试信息
编译时加上-g参数,方便后续排查问题:g++ test.cpp -std=c++11 -g -D_GLIBCXX_USE_CXX11_ABI=0 -lavrocpp
内容的提问来源于stack exchange,提问作者Dharmendra Koppineni
相关产品推荐
相关产品推荐

