C++ Thrift TThreadedServer编译错误:vtable for MessageProcessorFactory未定义引用
构建Thrift TThreadedServer时
undefined reference to vtable for MessageProcessorFactory错误排查 问题描述
构建Thrift TThreadedServer服务器时出现链接错误,编译日志提示undefined reference to vtable for MessageProcessorFactory,移除MessageProcessorFactory指针后错误消失。相关信息如下:
编译日志
[main] Building folder: Thrift_client_server [build] Starting build [proc] Executing command: /usr/bin/cmake --build "/home/konstantin/c++ projects/Thrift_client_server/build" --config Debug --target all -j 14 -- [build] Consolidate compiler generated dependencies of target server [build] [ 50%] Building CXX object CMakeFiles/server.dir/server.cpp.o [build] [100%] Linking CXX executable server [build] /usr/bin/ld: CMakeFiles/server.dir/server.cpp.o: warning: relocation against `_ZTV23MessageProcessorFactory' in read-only section `.text._ZN23MessageProcessorFactoryC2ERKSt10shared_ptrI16MessageIfFactoryE[_ZN23MessageProcessorFactoryC5ERKSt10shared_ptrI16MessageIfFactoryE]' [build] /usr/bin/ld: CMakeFiles/server.dir/server.cpp.o: in function `MessageProcessorFactory::MessageProcessorFactory(std::shared_ptr<MessageIfFactory> const&)': [build] /home/konstantin/c++ projects/Thrift_client_server/api/gen-cpp/Message.h:209: undefined reference to `vtable for MessageProcessorFactory' [build] /usr/bin/ld: warning: creating DT_TEXTREL in a PIE [build] collect2: error: ld returned 1 exit status [build] gmake[2]: *** [CMakeFiles/server.dir/build.make:98: server] Error 1 [build] gmake[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/server.dir/all] Error 2 [build] gmake: *** [Makefile:91: all] Error 2 [proc] The command: /usr/bin/cmake --build "/home/konstantin/c++ projects/Thrift_client_server/build" --config Debug --target all -j 14 -- exited with code: 2 [driver] Build completed: 00:00:01.631 [build] Build finished with exit code 2
原始CMakeLists.txt
cmake_minimum_required(VERSION 3.11) project(server) set(THRIFT_LIB_DIR "/home/konstantin/thrift/thrift-0.19.0") find_library(THRIFT_LIB thrift ${THRIFT_LIB_DIR}) add_executable(${PROJECT_NAME} server.cpp) target_link_libraries(${PROJECT_NAME} ${THRIFT_LIB})
服务器代码
#include <thrift/server/TThreadedServer.h> #include <thrift/transport/TServerSocket.h> #include <thrift/transport/TTransport.h> #include <thrift/TProcessor.h> #include <thrift/transport/TBufferTransports.h> #include <memory> #include <string> #include "api/gen-cpp/Message.h" using namespace ::apache::thrift::server; using namespace ::apache::thrift::protocol; using namespace ::apache::thrift::transport; using namespace ::apache::thrift; class MessageHandler : public MessageIf { public: virtual void mes(std::string &_return) override { _return = "Hello from the server"; } virtual ~MessageHandler(){} }; class MessageHandlerFactory : public MessageIfFactory { public: virtual MessageIf *getHandler(const ::apache::thrift::TConnectionInfo &connInfo) { return new MessageHandler(); } virtual void releaseHandler(MessageIf *handler) { delete handler; } virtual ~MessageHandlerFactory(){} }; int main(){ std::shared_ptr<MessageIfFactory> handler_factory = std::make_shared<MessageHandlerFactory>(); auto processor_factory = std::make_shared<MessageProcessorFactory>(handler_factory); auto transport_socket = std::make_shared<TServerSocket>(9090); auto transport_factory = std::make_shared<TFramedTransportFactory>(); auto protocol_factory = std::make_shared<TBinaryProtocolFactory>(); TThreadedServer server(processor_factory, transport_socket, transport_factory, protocol_factory); server.serve(); return 0; }
错误原因
MessageProcessorFactory是Thrift根据IDL文件自动生成的类,它的实现代码位于api/gen-cpp/Message.cpp中。当前CMakeLists.txt仅编译了server.cpp,未将生成的Message.cpp纳入编译流程,导致链接阶段找不到该类虚函数表(vtable)的定义,触发链接错误。
解决方法
步骤1:修改CMakeLists.txt,添加生成的源文件
将Thrift生成的Message.cpp添加到可执行文件的源列表,同时确保CMake能找到该文件路径:
cmake_minimum_required(VERSION 3.11) project(server) set(THRIFT_LIB_DIR "/home/konstantin/thrift/thrift-0.19.0") # 指定生成代码的目录 set(GEN_CPP_DIR "${PROJECT_SOURCE_DIR}/api/gen-cpp") find_library(THRIFT_LIB thrift ${THRIFT_LIB_DIR}) # 将生成的Message.cpp与server.cpp一同编译 add_executable(${PROJECT_NAME} server.cpp "${GEN_CPP_DIR}/Message.cpp" ) # 包含生成代码的头文件目录 target_include_directories(${PROJECT_NAME} PRIVATE ${GEN_CPP_DIR}) target_link_libraries(${PROJECT_NAME} ${THRIFT_LIB})
步骤2:重新构建项目
删除原有build目录,重新执行构建命令:
rm -rf build mkdir build cd build cmake .. make
修改后,编译流程会包含Message.cpp的代码,链接时即可找到MessageProcessorFactory的虚函数表定义,错误即可解决。
内容的提问来源于stack exchange,提问作者Behemoth
相关产品推荐
相关产品推荐

