调用`thisCap`segfaults

问题描述

我正在使用calculator-server.c++示例,在该示例中,我尝试提取thisCap()以从外部向服务器提供功能。因为thisCap()protected,所以我写了自己的公开getCapability()

class CalculatorImpl final: public Calculator::Server {
  // Implementation of the Calculator Cap'n Proto interface.

public:
  Calculator::Client getCapability() {
      return thisCap();
  }

然后,我创建服务器并从主服务器调用getCapability()

  auto calculatorImpl = kj::heap<CalculatorImpl>();
  auto myCapability = calculatorImpl->getCapability();

但这是段错误

Program received signal SIGSEGV,Segmentation fault.
0x000055555573c847 in capnp::Capability::Server::thisCap() ()
(gdb) bt
#0  0x000055555573c847 in capnp::Capability::Server::thisCap() ()
#1  0x000055555573c93d in Calculator::Server::thisCap() ()
#2  0x000055555573e541 in CalculatorImpl::getCapability() ()
#3  0x0000555555739a98 in main ()

根据消息来源,我最终进入this

Capability::Client Capability::Server::thisCap() {
  return Client(thisHook->addRef());
}

所以看来thisHook一个nullptr,因为它是how it is initialized,所以很有意义。

我只是不太了解它在什么时候初始化了(this解释了什么时候绝对没有初始化)。

有什么主意吗?

解决方法

thisCap()仅在创建至少一个指向您的服务器对象的Client对象之后才能工作。要创建该初始Client,只需声明一个客户端类型的变量并将其初始化为服务器对象,如下所示:

Calculator::Client cap = kj::heap<CalculatorImpl>();

如果即使在构造Client之后仍要保留对基础服务器对象的引用,则可以执行以下操作:

kj::Own<CalculatorImpl> server = kj::heap<CalculatorImpl>();
CalculatorImpl& ref = *server;
Calculator::Client cap = kj::mv(server);

请注意,一旦创建了第一个Client,服务器将在不再有指向它的Client(包括远程Client)时被销毁。因此,如果您想确保引用保持有效,请确保还保留Client的副本。

通常,thisCap()用于RPC方法的实现。用您的getCapability()方法向外部调用者公开它是不寻常的。这是因为,如果调用者尚未持有指向该对象的Client,则无法知道该对象是否仍然存在,因此调用类似{{1}的方法是不安全的}。