You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

添加--coverage标志时出现grpc::experimental虚表未定义引用错误

问题

我有一个基于CMake的C++项目,初始结构由cmake-init创建。集成gRPC后,启用--coverage编译标志时出现链接错误,不启用该标志则正常,且代码中并未直接使用AuthorizationPolicy相关功能。

链接错误信息

[build] /usr/bin/ld: CMakeFiles/demo_lib.dir/source/lib.cpp.o: warning: relocation against `_ZTVN4grpc12experimental38FileWatcherAuthorizationPolicyProviderE' in read-only section `.text._ZN4grpc12experimental38FileWatcherAuthorizationPolicyProviderC2EP34grpc_authorization_policy_provider[_ZN4grpc12experimental38FileWatcherAuthorizationPolicyProviderC5EP34grpc_authorization_policy_provider]'
[build] /usr/bin/ld: /usr/bin/ld: ../CMakeFiles/demo_lib.dir/source/lib.cpp.o: warning: relocation against `_ZTVN4grpc12experimental38FileWatcherAuthorizationPolicyProviderE' in read-only section `.text._ZN4grpc12experimental38FileWatcherAuthorizationPolicyProviderC2EP34grpc_authorization_policy_provider[_ZN4grpc12experimental38FileWatcherAuthorizationPolicyProviderC5EP34grpc_authorization_policy_provider]'
[build] /usr/bin/ld: ../CMakeFiles/demo_lib.dir/source/lib.cpp.o: in function `grpc::experimental::StaticDataAuthorizationPolicyProvider::StaticDataAuthorizationPolicyProvider(grpc_authorization_policy_provider*)':
[build] /home/toto/development/cmake-init-tuto/demo/build/coverage/vcpkg_installed/x64-linux/include/grpcpp/security/authorization_policy_provider.h:48: undefined reference to `vtable for grpc::experimental::StaticDataAuthorizationPolicyProvider'
[build] /usr/bin/ld: ../CMakeFiles/demo_lib.dir/source/lib.cpp.o: in function `grpc::experimental::FileWatcherAuthorizationPolicyProvider::FileWatcherAuthorizationPolicyProvider(grpc_authorization_policy_provider*)':
[build] /home/toto/development/cmake-init-tuto/demo/build/coverage/vcpkg_installed/x64-linux/include/grpcpp/security/authorization_policy_provider.h:73: undefined reference to `vtable for grpc::experimental::FileWatcherAuthorizationPolicyProvider'
[build] CMakeFiles/demo_lib.dir/source/lib.cpp.o: in function `grpc::experimental::StaticDataAuthorizationPolicyProvider::StaticDataAuthorizationPolicyProvider(grpc_authorization_policy_provider*)':
[build] /home/toto/development/cmake-init-tuto/demo/build/coverage/vcpkg_installed/x64-linux/include/grpcpp/security/authorization_policy_provider.h:48: undefined reference to `vtable for grpc::experimental::StaticDataAuthorizationPolicyProvider'
[build] /usr/bin/ld: CMakeFiles/demo_lib.dir/source/lib.cpp.o: in function `grpc::experimental::FileWatcherAuthorizationPolicyProvider::FileWatcherAuthorizationPolicyProvider(grpc_authorization_policy_provider*)':
[build] /home/toto/development/cmake-init-tuto/demo/build/coverage/vcpkg_installed/x64-linux/include/grpcpp/security/authorization_policy_provider.h:73: undefined reference to `vtable for grpc::experimental::FileWatcherAuthorizationPolicyProvider'

项目配置

代码结构与exmpl-cmake-grpc仓库基本一致,仅将入口改为void launch_server()由int main()调用。CMakePresets.json相关配置如下:

{
      "name": "flags-unix",
      "hidden": true,
      "cacheVariables": {
        "CMAKE_CXX_FLAGS": "-Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wcast-qual -Wformat=2 -Wundef -Werror=float-equal -Wshadow -Wcast-align -Wunused -Wnull-dereference -Wdouble-promotion -Wimplicit-fallthrough -Wextra-semi -Woverloaded-virtual -Wnon-virtual-dtor -Wold-style-cast -Wl,--whole-archive -Wl,--allow-multiple-definition"
      }
    },
{
      "name": "coverage-unix",
      "binaryDir": "${sourceDir}/build/coverage",
      "inherits": "ci-unix",
      "hidden": true,
      "cacheVariables": {
        "ENABLE_COVERAGE": "ON",
        "CMAKE_BUILD_TYPE": "Coverage",
        "CMAKE_CXX_FLAGS_COVERAGE": "-Og -g --coverage -fkeep-inline-functions -fkeep-static-functions",
        "CMAKE_EXE_LINKER_FLAGS_COVERAGE": "--coverage",
        "CMAKE_SHARED_LINKER_FLAGS_COVERAGE": "--coverage",
        "CMAKE_MAP_IMPORTED_CONFIG_COVERAGE": "Coverage;RelWithDebInfo;Release;Debug;"
      }
    },

补充说明

  • 代码仅通过ServerBuilder间接关联到AuthorizationPolicyProvider,该类定义片段:
class ServerBuilder {
 public:
  ServerBuilder();
  virtual ~ServerBuilder();
  // (...)
  class experimental_type {
   public:
    // (...)
    void SetAuthorizationPolicyProvider(
        std::shared_ptr<experimental::AuthorizationPolicyProviderInterface>
            provider);

   private:
    ServerBuilder* builder_;
  };
  //(...)
  private:
  std::shared_ptr<experimental::AuthorizationPolicyProviderInterface>
      authorization_provider_;
  • 检查过对应的头文件,未发现未定义的纯虚函数。

解决方案

1. 显式链接gRPC安全库

gRPC的AuthorizationPolicyProvider相关实现位于grpc++_security库中,coverage编译模式下的优化差异可能触发了对这些类的隐式引用。在CMake目标中添加该库链接:

target_link_libraries(your_target_name
  PRIVATE
    grpc++
    grpc++_security  # 新增该行
    # 其他依赖库
)

2. 调整coverage编译选项

当前CMAKE_CXX_FLAGS_COVERAGE中的-fkeep-inline-functions -fkeep-static-functions会强制保留所有内联/静态函数,可能间接触发未使用类的引用。尝试移除这两个选项:

"CMAKE_CXX_FLAGS_COVERAGE": "-Og -g --coverage"

若需保留特定内联函数,可针对性设置,而非全局强制保留。

3. 排查--whole-archive链接选项的影响

flags-unix配置中的-Wl,--whole-archive会强制链接库中所有符号,可能拉进未使用的AuthorizationPolicy相关符号。在coverage配置中覆盖该选项,移除全局的--whole-archive:

// 在coverage-unix的cacheVariables中添加
"CMAKE_CXX_FLAGS": "-Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wcast-qual -Wformat=2 -Wundef -Werror=float-equal -Wshadow -Wcast-align -Wunused -Wnull-dereference -Wdouble-promotion -Wimplicit-fallthrough -Wextra-semi -Woverloaded-virtual -Wnon-virtual-dtor -Wold-style-cast -Wl,--allow-multiple-definition"

4. 重新编译gRPC的coverage版本

vcpkg安装的预编译gRPC库可能在coverage模式下存在符号缺失。可修改vcpkg triplet配置添加coverage编译选项,重新安装gRPC:

vcpkg install grpc:x64-linux --overlay-triplets=your-triplet-dir

内容的提问来源于stack exchange,提问作者mmnano50

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 07:25:32