GCC infers pass-by-value copy assignment with jsoncpp

Viewed 108
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);
}

In our case, we tried to build a shared lib with a proto to json function The linked app would crash with no core dump and we got output in gdb as

Inferior 1 (process xxx) exited with code 0177

and _dl_signal_error frame.

Code line resulted in the error was

value[field_ptr->name()] = reflection_ptr->GetUInt32(msg, field_ptr);

and we found that ldd -r shows the shared lib has undefined symbol pointing to _ZN4Json5ValueaSES0_, demangled as Json::Value::operator=(Json::Value) by c++filt

It surprised us a lot because there was no pass-by-value copy assignment function in jsoncpp's headers or source code. We tried recompile it with latest release of jsoncpp and the problem remains

However, when we make a stand alone jsoncpp demo, it works fine and ldd -r no longer shows the undefined symbol output

We guess it's gcc which interprets and chooses a non-existent copy assignment operator. It may be relevant to copy emision or other optimization, how can we fix it? or how to explicitly use a valid copy assignment operator?

Linux version we use is Linux version 2.6.32-696.el6.x86_64 CentOS release 6.9 (Final), gcc version is gcc (GCC) 9.1.0

compiling options are

C_FLAGS          = -Wall -D_GNU_SOURCE  -Wno-deprecated -fPIC -g -pipe -D_DEBUG -Woverloaded-virtual -Wpointer-arith -fno-strict-aliasing -std=c++17

and link with jsoncpp static lib

1 Answers

The by-value assignment operator has been replaced by by-reference assignment operators starting with version 1.9.0 of the library, see https://github.com/open-source-parsers/jsoncpp/commit/0c1cc6e1a373dc58e2599ec7dd68b2e6b863990a#.

The assignment operators are not defined inline and so a pre-1.9.x version of the library will contain a definition of the by-value version, while a 1.9.x version will not.

It is likely that you are either compiling against the headers of a pre-1.9.x version while trying to link/load a 1.9.x version of the library or the other way around.

According to the readme page on the github major versions (not sure if only 1.x or 1.9.x is meant) are supposed to be binary-compatible, but I don't think that this change is a binary-compatible change.

There is a closed issue on the project's github describing the same problem without conclusive answer: https://github.com/open-source-parsers/jsoncpp/issues/738

Related