C++ 对 google::protobuf::internal::empty_string_[abi:cxx11] 的未定义引用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30124264/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 13:42:35  来源:igfitidea点击:

Undefined reference to google::protobuf::internal::empty_string_[abi:cxx11]

c++gccprotocol-buffers

提问by Ragnar

I'm trying to build simple test application with Protocol Buffers 2.6.1 and GNU GCC 5.1.0 (on Ubuntu 14.10) and I get following errors:

我正在尝试使用 Protocol Buffers 2.6.1 和 GNU GCC 5.1.0(在 Ubuntu 14.10 上)构建简单的测试应用程序,但出现以下错误:

/home/ragnar/cpp-tools/gcc-linux/bin/g++   -c  "/home/ragnar/cpp-projects/gprotobuf_test/main.cpp" -g -O0 -Wall   -o ./Debug/main.cpp.o -I. -I/home/ragnar/cpp-tools/libs/linux64/protobuf/include -I.
/home/ragnar/cpp-tools/gcc-linux/bin/g++   -c  "/home/ragnar/cpp-projects/gprotobuf_test/messages.pb.cc" -g -O0 -Wall   -o ./Debug/messages.pb.cc.o -I. -I/home/ragnar/cpp-tools/libs/linux64/protobuf/include -I.  
/home/ragnar/cpp-tools/gcc-linux/bin/g++  -o ./Debug/gprotobuf_test @"gprotobuf_test.txt" -L. -L/home/ragnar/cpp-tools/libs/linux64/protobuf/lib  -lprotobuf  
./Debug/main.cpp.o: In function google::protobuf::internal::GetEmptyStringAlreadyInited[abi:cxx11]():  
  /home/ragnar/cpp-tools/libs/linux64/protobuf/include/google/protobuf/generated_message_util.h:80: 
    undefined reference to google::protobuf::internal::empty_string_[abi:cxx11]  
  /home/ragnar/cpp-tools/libs/linux64/protobuf/include/google/protobuf/generated_message_util.h:81: 
    undefined reference to google::protobuf::internal::empty_string_[abi:cxx11]  
./Debug/messages.pb.cc.o: In function protobuf_AssignDesc_messages_2eproto():  
  /home/ragnar/cpp-projects/gprotobuf_test/messages.pb.cc:32: 
    undefined reference to google::protobuf::DescriptorPool::FindFileByName(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const  
./Debug/messages.pb.cc.o: In function protobuf_AddDesc_messages_2eproto():  
  /home/ragnar/cpp-projects/gprotobuf_test/messages.pb.cc:83: 
    undefined reference to google::protobuf::MessageFactory::InternalRegisterGeneratedFile(char const*, void (*)(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&))  
./Debug/messages.pb.cc.o: In function my_message::MergePartialFromCodedStream(google::protobuf::io::CodedInputStream*):
  /home/ragnar/cpp-projects/gprotobuf_test/messages.pb.cc:187: 
    undefined reference to google::protobuf::internal::WireFormatLite::ReadString(google::protobuf::io::CodedInputStream*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)  
./Debug/messages.pb.cc.o: In function my_message::SerializeWithCachedSizes(google::protobuf::io::CodedOutputStream*) const:
  /home/ragnar/cpp-projects/gprotobuf_test/messages.pb.cc:247: 
    undefined reference to google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, google::protobuf::io::CodedOutputStream*)  
./Debug/messages.pb.cc.o: In function google::protobuf::internal::WireFormatLite::WriteStringToArray(int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned char*):
  /home/ragnar/cpp-tools/libs/linux64/protobuf/include/google/protobuf/wire_format_lite_inl.h:749: 
    undefined reference to google::protobuf::io::CodedOutputStream::WriteStringWithSizeToArray(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned char*)  
./Debug/messages.pb.cc.o:(.rodata._ZTV10my_message[_ZTV10my_message]+0x20): 
    undefined reference to google::protobuf::Message::GetTypeName[abi:cxx11]() const  
 ./Debug/messages.pb.cc.o:(.rodata._ZTV10my_message[_ZTV10my_message]+0x40): 
    undefined reference to google::protobuf::Message::InitializationErrorString[abi:cxx11]() const  
collect2: error: ld returned 1 exit status  
gprotobuf_test.mk:93: recipe for target "Debug/gprotobuf_test" failed  
make[1]: *** [Debug/gprotobuf_test] Error 1  
make[1]: Leaving directory "/home/ragnar/cpp-projects/gprotobuf_test"  
Makefile:4: recipe for target "All" failed  
make: *** [All] Error 2  

The /home/ragnar/cpp-tools/libs/linux64/protobuf/lib contains following libraries:

/home/ragnar/cpp-tools/libs/linux64/protobuf/lib 包含以下库:

libprotobuf.a  
libprotobuf.so.9.0.1  
libprotobuf-lite.a  
libprotobuf-lite.so.9.0.1  
libprotoc.a  
libprotoc.so.9.0.1  

Here's the simple messages.proto file:

这是简单的 messages.proto 文件:

option java_package = "my.package";

message my_message {
  required string word = 1;
  required uint32 number = 2;
}

and the code I'm trying to get working:

和我试图开始工作的代码:

#include <iostream>
#include <vector>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include "messages.pb.h"

std::vector<unsigned char> encode( google::protobuf::Message & msg )
{
  std::vector<unsigned char> data( msg.ByteSize() + 
    google::protobuf::io::CodedOutputStream::VarintSize32( msg.ByteSize() ) );
  google::protobuf::io::ArrayOutputStream array_out( &data[0], data.size() );
  google::protobuf::io::CodedOutputStream coded_out( &array_out );
  coded_out.WriteVarint32( msg.ByteSize() );
  msg.SerializeToCodedStream( &coded_out );
  return data;
}

void decode( const std::vector<unsigned char> & data, google::protobuf::Message & msg )
{
  google::protobuf::io::ArrayInputStream array_in( &data[0] , data.size() );
  google::protobuf::io::CodedInputStream coded_in( &array_in );
  google::protobuf::uint32 size;
  coded_in.ReadVarint32( &size );
  google::protobuf::io::CodedInputStream::Limit msg_limit = coded_in.PushLimit( size );
  msg.ParseFromCodedStream( &coded_in );
  coded_in.PopLimit( msg_limit );
}

int main(int argc, char **argv)
{
  my_message in_msg;
  in_msg.set_word( \"blah blah\" );
  in_msg.set_number( 123 );
  std::vector<unsigned char> data = encode( in_msg );

  my_message out_msg;
  decode( data, out_msg );
  std::cout << \"word: \" << out_msg.word() << \" number: \" << out_msg.number() << std::endl;
  return 0;
}

Gcc is built from source with following options:

Gcc 是从源代码构建的,具有以下选项:

--enable-64bit --enable-32bit --enable-languages=c,c++ --enable-multilib
--disable-nls --enable-threads=posix --enable-checking=release
--enable-lto --enable-multiarch --with-multilib-list=m32,m64,mx32 
--with-tune=generic --enable-shared --with-glibc-version=2.13
--enable-libstdcxx-time=rt

and Protobuf is built from source with following options:

和 Protobuf 是从源代码构建的,具有以下选项:

--enable-64it --disable-32bit --enable-shared CXXFLAGS=-m64 -DNDEBUG LDFLAGS=-m64

Any help would be greatly appreciated.

任何帮助将不胜感激。

回答by Kenton Varda

I suspect this is a C++ ABI issue. The ABI for std::stringhas changed in GCC 5 (related to C++11 requirements, but it applies even if you aren't using C++11). See:

我怀疑这是 C++ ABI 问题。std::stringGCC 5 中的 ABI已更改(与 C++11 要求相关,但即使您不使用 C++11,它也适用)。看:

https://gcc.gnu.org/gcc-5/changes.html#libstdcxx

https://gcc.gnu.org/gcc-5/changes.html#libstdcxx

If libprotobuf was built with GCC 4.x or prior, but your app is built with GCC 5, then you will see problems, because libprotobuf uses std::stringin its interface. You have two options:

如果 libprotobuf 是使用 GCC 4.x 或更早版本构建的,但您的应用程序是使用 GCC 5 构建的,那么您将看到问题,因为 libprotobufstd::string在其界面中使用。您有两个选择:

  1. Rebuild libprotobuf with GCC 5 (but now any apps built with GCC 4 won't work with the new version of libprotobuf).
  2. Build you app with -D_GLIBCXX_USE_CXX11_ABI=0as described at the above link. This will force GCC to use the old ABI version.
  1. 使用 GCC 5 重建 libprotobuf(但现在任何使用 GCC 4 构建的应用程序都无法与新版本的 libprotobuf 一起使用)。
  2. -D_GLIBCXX_USE_CXX11_ABI=0按照上述链接中的说明构建您的应用程序。这将强制 GCC 使用旧的 ABI 版本。

回答by Akanksha Gupta

I had similar problem as

我有类似的问题

writeProto.cpp:(.text+0x2a8): undefined reference to `google::protobuf::internal::VerifyVersion(int, int, char const*)'
writeProto.cpp:(.text+0x308): undefined reference to `tutorial::AddressBook::AddressBook()'
writeProto.cpp:(.text+0x3a2): undefined reference to `google::protobuf::Message::ParseFromIstream(std::istream*)'
writeProto.cpp:(.text+0x463): undefined reference to `google::protobuf::Message::SerializeToOstream(std::ostream*) const'
writeProto.cpp:(.text+0x4b4): undefined reference to `google::protobuf::ShutdownProtobufLibrary()'
writeProto.cpp:(.text+0x4c8): undefined reference to `tutorial::AddressBook::~AddressBook()'
writeProto.cpp:(.text+0x515): undefined reference to `tutorial::AddressBook::~AddressBook()'

I wrote this on the command line and now my code is working.

我在命令行上写了这个,现在我的代码正在运行。

c++ writeProto.cpp addressbook.pb.cc `pkg-config --cflags --libs protobuf`

回答by RasmusWL

I had a similar problem, that was caused by the fact that I compiled the protobuf library with GNU's libstdc++, but in the application I was using Clang's libc++, and the two don't work together.

我有一个类似的问题,这是因为我用 GNU 编译了 protobuf 库libstdc++,但是在应用程序中我使用的是 Clang 的libc++,并且两者不能一起工作。

It all became clear once I used ldd <file>to see what shared objects that file depends on.

一旦我过去ldd <file>查看文件所依赖的共享对象,一切就变得清晰了。