虚拟功能和助推绑定奇怪的行为
Virtual function and boost bind strange behavior
我在Linux下编写的一段代码中看到了一个奇怪的行为,我想分享一下,看看是否有人知道原因。我有一个基类和一个派生类。在基类中,我定义了一个虚拟方法,在派生类中,我用相同的签名重新定义了该方法。然后我使用boost绑定来启动一个线程。这是一个示例代码:
Class Base {
public:
virtual void DoSomething();
virtual void Init() = 0;
...
}
Class Derived : public Base {
public:
void DoSomething();
void Init();
...
}
在派生类的Init方法中,我这样做了:
boost::thread *t = new boost::thread(boost::bind(&Base::DoSomething, this));
基类的DoSomething方法做了它应该做的事情,而派生类的相同方法是一个空方法,错误地留在了那里。现在,在运行上面的代码时,大多数时候基类的DoSomething都是在线程中执行的,因此应用程序运行良好,但有时不起作用。经过一些调试,我注意到了上面的错误,删除派生类的DoSomething解决了这个问题。在调试模式下使用Eclipse,似乎总是调用派生类的DoSomething方法,而从控制台运行应用程序在大多数情况下都有效,但并非总是如此。这种行为有原因吗?我的意思是,为什么绑定函数有时使用基类方法,有时使用派生类的相同方法?
提前感谢
编辑以响应@pmr
很难展示一个完整的工作示例,我将尝试展示一些类是如何使用的。
首先我实例化一个Derived对象,然后在init函数中用上面显示的初始化代码启动线程。DoSomething有一个在向量上迭代的while循环,但我认为这不是重点。
void Derived::Init()
{
...
boost::thread *t = new boost::thread(boost::bind(&Base::DoSomething, this));
}
void Base::DoSomething()
{
while(true) {
...
}
}
void Derived::DoSomething()
{
}
正如您在这段代码中看到的,Derived DoSomething方法是空的,所以有时我没有看到任何处理,而是在Base DoSometing函数中进行。
这里有一个疯狂的猜测:用于启动线程的对象实际上被破坏了!由于虚拟函数的绑定在销毁过程中发生了变化(当对象被销毁时,所有虚拟函数都会解析为所使用的对象是当前正在销毁的类的类型)。为此,"vtable指针"通常会重置为指向合适的"虚拟函数表"。一旦基地被摧毁,就不需要进一步摧毁物体了。
这与您对行为随机性的解释非常吻合:有时父线程执行得足够快,可以到达基类构造函数,有时则不然。在使用调试模式进行编译时,父线程显然在销毁对象之前持续了很长时间。你所说的在很多情况下一切都很好,这也并没有真正破坏这一形象:通常有缺陷的代码看起来似乎是有效的,尽管在更仔细地检查时,它实际上显示出了错误的行为。
我想我已经找到了这种行为的原因:起初我在基类构造函数中调用了线程构造函数。我认为这就是问题所在,因为基构造函数是在派生构造函数之前调用的,有时vtable是指向空的派生函数创建的,有时线程是在vtable创建之前启动的,因此bind函数使用了基方法,这就是它的目的。我想使用debug会引入一些延迟,所以使用调试器时线程总是绑定到派生类方法,从而导致错误的行为。此外,我还尝试将线程创建转移到init函数中,这样就总是调用派生函数。
我们在内部操作系统中遇到了同样的问题,在构建对象时,我们将一些虚拟函数绑定到另一个工作线程。如果操作系统在派生类的构造函数之前切换到工作线程,工作线程将使用基类类型调用"this"。所以,我认为我们可以描述它:"this"指针在构造函数和去构造函数中是不线程安全的。
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 在基于范围的for循环中使用结构化绑定声明
- 使用提升功能与地图绑定提升
- 绑定和提升功能
- C++ 由于无法解决过载功能而导致绑定失败
- C 使用多个lambdas/绑定以引用相同的功能
- 实现功能对象绑定而无需使用C 11
- 尝试将简单按钮绑定到SFGUI中的OnClick功能
- 绑定std ::功能错误
- rvalue参考绑定到std ::功能类型的LVALUE
- 如何拆分功能:绑定
- 转换std ::绑定到功能指针
- C 快速绑定成员功能的方法
- 如何绑定变异模板参数与功能
- STD ::绑定和超载功能
- 试图了解动态绑定和虚拟功能
- 消除对Boost ::的需求,以绑定我的功能
- C 预处理器中的功能绑定操作
- 虚拟功能和助推绑定奇怪的行为
- XML数据绑定-可以自动完成读/写功能