const Descriptor* descriptor_ptr = msg.GetDescriptor();
const Reflection* reflection_ptr = msg.GetReflection();
const FieldDescriptor* field_ptr = descriptor_ptr->field(i);
Json::Value value;
if (field_ptr->cpp_type() == FieldDescriptor::CPPTYPE_UINT32)
{
value[field_ptr->name()] = reflection_ptr->GetUInt32(msg, field_ptr);
}
在我们的例子中,我们尝试构建一个带有 proto 到 json 函数的共享库 链接的应用程序会在没有核心转储的情况下崩溃,我们在 gdb 中得到了输出
Inferior 1 (process xxx) exited with code 0177
和_dl_signal_error
帧。
导致错误的代码行是
value[field_ptr->name()] = reflection_ptr->GetUInt32(msg, field_ptr);
我们发现 ldd -r
显示共享库有指向 _ZN4Json5ValueaSES0_
的 undefined symbol ,分解为 Json::Value::operator=(Json::Value)
由 c++filt
让我们很吃惊的是,jsoncpp的头文件和源码中都没有传值复制赋值函数。我们尝试用最新版本的 jsoncpp 重新编译它,问题仍然存在
但是,当我们制作一个独立的 jsoncpp 演示时,它工作正常并且 ldd -r
不再显示 undefined symbol 输出
我们猜测是 gcc 解释并选择了一个不存在的复制赋值运算符。它可能与复制排放或其他优化有关,我们该如何解决?或者如何显式使用有效的复制赋值运算符?
我们使用的Linux版本是Linux version 2.6.32-696.el6.x86_64
CentOS release 6.9 (Final)
,gcc版本是gcc (GCC) 9.1.0
编译选项是
C_FLAGS = -Wall -D_GNU_SOURCE -Wno-deprecated -fPIC -g -pipe -D_DEBUG -Woverloaded-virtual -Wpointer-arith -fno-strict-aliasing -std=c++17
并链接到jsoncpp静态库
最佳答案
从库的 1.9.0 版开始,按值赋值运算符已被按引用赋值运算符取代,请参阅 https://github.com/open-source-parsers/jsoncpp/commit/0c1cc6e1a373dc58e2599ec7dd68b2e6b863990a# .
赋值运算符不是内联定义的,因此 1.9.x 之前版本的库将包含按值版本的定义,而 1.9.x 版本则不会。
很可能您在尝试链接/加载库的 1.9.x 版本时针对 1.9.x 之前版本的 header 进行编译,或者相反。
根据 github 主要版本上的自述文件页面(不确定是否只有 1.x
或 1.9.x
是指)应该是二进制兼容的,但我不认为此更改是二进制兼容的更改。
项目的 github 上有一个已关闭的问题,描述了相同的问题但没有确定的答案:https://github.com/open-source-parsers/jsoncpp/issues/738
关于c++ - GCC 使用 jsoncpp 推断传值复制赋值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70754875/