C++ gRPC trace.cc的方法TraceFlagList::Add(TraceFlag*flag)使其链表循环到自身

C++ gRPC trace.cc的方法TraceFlagList::Add(TraceFlag*flag)使其链表循环到自身,c++,grpc,C++,Grpc,我正在为32位Atom硬件集成gRPC。gRPC是在64位Ubuntu PC计算机上交叉编译的。交叉编译使用Yocto。gRPC的CMakeLists.txt文件通过add_subdirectory()函数包含在主项目中,并以静态方式链接。为了测试GRPC,我使用谷歌的C++语音样本代码。p> 完整的项目构建正确,部署在目标硬件上没有问题。当我运行示例程序时,在trace.cc文件的方法TraceFlagList::Set(const char*name,bool enabled)中的无限循环中

我正在为32位Atom硬件集成gRPC。gRPC是在64位Ubuntu PC计算机上交叉编译的。交叉编译使用Yocto。gRPC的CMakeLists.txt文件通过add_subdirectory()函数包含在主项目中,并以静态方式链接。为了测试GRPC,我使用谷歌的C++语音样本代码。p> 完整的项目构建正确,部署在目标硬件上没有问题。当我运行示例程序时,在trace.cc文件的方法TraceFlagList::Set(const char*name,bool enabled)中的无限循环中停止执行

为了检查这个问题,我在这个方法中的每个循环中放置了一些printf():

bool TraceFlagList::Set(const char* name, bool enabled) {
  TraceFlag* t;
  if (0 == strcmp(name, "all")) {
    for (t = root_tracer_; t; t = t->next_tracer_) {
      printf("%s 1 %s\n", __func__, t->name_);
      t->set_enabled(enabled);
    }
  } else if (0 == strcmp(name, "list_tracers")) {
    LogAllTracers();
  } else if (0 == strcmp(name, "refcount")) {
    for (t = root_tracer_; t; t = t->next_tracer_) {
      printf("%s 2 %s\n", __func__, t->name_);
      if (strstr(t->name_, "refcount") != nullptr) {
        t->set_enabled(enabled);
      }
    }
  } else {
    bool found = false;
    for (t = root_tracer_; t; t = t->next_tracer_) {
      printf("%s 3 %s\n", __func__, t->name_);
      if (0 == strcmp(name, t->name_)) {
        t->set_enabled(enabled);
        found = true;
      }
    }
    // check for unknowns, but ignore "", to allow to GRPC_TRACE=
    if (!found && 0 != strcmp(name, "")) {
      gpr_log(GPR_ERROR, "Unknown trace var: '%s'", name);
      return false; /* early return */
    }
  }
  return true;
}
似乎在TraceFlagList对象中多次添加了一些TraceFlag指针。以下是添加方法:

void TraceFlagList::Add(TraceFlag* flag) {
  flag->next_tracer_ = root_tracer_;
  root_tracer_ = flag;
}

要添加的第一个元素的下一个_tracer_uu成员指向null。但在多次添加之后,将使用相同的TraceFlag指针再次调用TraceFlagList::Add()。第一个将使其下一个_tracer u成员指向列表的最后一个元素,使列表循环到自身

运行可执行文件会在命令行中显示以下行:

...
Set 3 api
Set 3 timer_check
Set 3 timer
Set 3 resource_quota
Set 3 executor
Set 3 bdp_estimator
Set 3 client_idle_filter
Set 3 cares_resolver
Set 3 cares_address_sorting
Set 3 round_robin
Set 3 pick_first
Set 3 xds
Set 3 glb
Set 3 inproc
Set 3 health_check_client
Set 3 secure_endpoint
Set 3 http2_stream_state
Set 3 flowctl
Set 3 http
Set 3 connectivity_state
Set 3 tcp
Set 3 http1
Set 3 handshaker
Set 3 channel
Set 3 subchannel_pool
Set 3 subchannel
Set 3 client_channel_routing
Set 3 client_channel_call
Set 3 tsi
Set 3 plugin_credentials
Set 3 server_channel
Set 3 queue_pluck
Set 3 op_failure
Set 3 compression
Set 3 call_error
Set 3 api
Set 3 timer_check
Set 3 timer
Set 3 resource_quota
Set 3 executor
Set 3 bdp_estimator
Set 3 client_idle_filter
Set 3 cares_resolver
Set 3 cares_address_sorting
^C
我必须用ctrl+c来中断可执行文件以停止它。我通过首先检查要添加到列表中的元素的存在性来解决问题:

void TraceFlagList::Add(TraceFlag* flag) {
  // Check TraceFlag existence in the list before adding it.
  for (const TraceFlag* t = root_tracer_; t != nullptr; t = t->next_tracer_) {
    if (t == flag) {
      gpr_log(GPR_DEBUG, "\t%s", t->name_);
      printf("TraceFlag %s already in TraceFlagList. Ignore.\n", t->name_);
      return;
    }
  }

  flag->next_tracer_ = root_tracer_;
  root_tracer_ = flag;
}
但这是一个解决办法:在为Ubuntu主机构建和运行原始代码时,不存在无限循环的问题。每个TraceFlag指针只添加一次。我真的不知道gRPC中使用TraceFlag的目的是什么

我担心这种变通方法可能会隐藏真正的问题,这可能会产生意想不到的副作用。有人知道这个问题的起因吗?或者,我应该提出gRPC项目的解决方案吗

问候。

这看起来像 grpc core使用一些全局变量,如果您以某种方式链接了多个版本的grpc库,则全局变量会损坏。

这看起来像
grpc core使用一些全局变量,如果您以某种方式链接了多个版本的grpc库,则全局变量会损坏。

您还可以
导出grpc\u VERBOSITY=DEBUG
导出grpc\u TRACE=list\u tracers
(将导出替换为set for windows)查看无限列表(很像问题中的日志记录)没有任何grpc代码更改。我在32位centos VMOS上使用的是32位版本。您还可以
导出GRPC_VERBOSITY=DEBUG
导出GRPC_TRACE=list_tracers
(将导出替换为set for windows)查看无限列表(很像问题中的日志记录),而无需任何GRPC代码更改。我在32位centos虚拟机上使用32位版本