纯虚函数怎么被调用?

4

我正在使用libPoco创建一个虚拟服务器来测试一些客户端代码。

class ServerRunnable: public Poco::Runnable {
  public:
ServerRunnable(StreamSocket conn) : conn(conn) {
}

void run(){
  string mess("Can you hear me?\n");
  try{
    this->conn.sendBytes(mess.c_str(), mess.size());
  } catch (Poco::Exception& ex){
    cerr << ex.displayText() << endl;
    return;
  }
  cerr << "The message has been sent." << endl;
}

void setConn(StreamSocket inConn){
  this->conn = inConn;
}
  private:
StreamSocket conn;
};


int main(int argc, char **argv){
  ServerSocket s;
  try{
    s.bind(8083, true);
  } catch (Exception &ex){
    cerr << ex.displayText() << endl;
    exit(1);
  }
  s.listen(124);

  Poco::ThreadPool Pool(10, 25, 60, 128);
  while(1){
    try{
      StreamSocket conn = s.acceptConnection();
      ServerRunnable serveIt(conn);

      Pool.start(serveIt);
    }  catch (Exception &ex){
      cerr << ex.displayText() << endl;
      Pool.joinAll();
      exit(1);
    }
  } 
  return 0;
 }

Poco::Runnable 是一个抽象类,我相信其中的 run 函数是一个纯虚函数。Pool.start(serveIt) 似乎在调用 ServerRunnablerun 函数。当我从控制台运行它时,我经常会得到“pure virtual method called”错误。然而,如果我在 gdb 中逐步执行代码,那么我将成功接受来自客户端的连接并向其发送数据。 ServerRunnablerun 不是一个纯虚函数,应该被调用。

libPoco 的线程的代码示例可以在 http://pocoproject.org/slides/130-Threads.pdf 找到。

我还在考虑可能是在构造函数中调用了纯虚函数,但构造函数中没有任何内容,我只使用默认析构函数。有没有办法确定正在调用哪个纯虚函数以及在哪里?在 gdb 中?谢谢。

2个回答

7
问题很可能是您的serverIt对象在其run方法被调用之前超出了作用域。 您无法控制线程何时运行,因此可能是循环在类的run方法被调用之前迭代,但然后您的对象已被销毁,并且随着其销毁当然也会销毁虚函数表。

2
我同意这很可能是发生的情况。导致调用纯虚函数的一般情况是,在构造函数完成之前或析构函数开始之后调用了虚函数。 - Ben Voigt

2
Pool.start()

启动一个线程并返回。这就是为什么在你提供的PDF中,他们的线程池示例看起来像这样:

main()
    Poco::ThreadPool::defaultPool().start(runnable);
    Poco::ThreadPool::defaultPool().joinAll();
    return 0;

当您在gdb中逐步执行时,您给线程时间来完成其任务,然后实例变量才会超出范围。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接