我的应用程序有时会崩溃,因为_purecall
正在调用 MS,但我在故障转储中看到的数据不是我所期望的。
我CSocket
派生自CConnection
,后者有一个名为的纯虚函数DoRead
,当一个实例CSocket
在工作线程中调用此函数时,应用程序崩溃。
根据寄存器值以及 Microsoft 如何实现 C++ 虚拟表和调用,我看到RCX
了正确的this
值,第一个四字指向 v-table 并且 v-table 是正确的,因此_purecall
不应发生调用。
但是在看到构造函数是如何实现的之后,我看到CConnection
构造函数设置了指向 v-table 的指针,其中包括调用_purecall
然后,CSocket
的构造函数用正确/派生的 v-table 覆盖这个值。
这就是我怀疑正在发生的事情:
- 一个线程调用
new CSocket
. - 在
CSocket
调用构造函数和修改 v-table 之前,工作线程读取指针附近的一些内存(可能是因为它正在处理其他CSocket
实例的操作)并且该内存页面被处理器“缓存”。 - 线程创建
CSocket
继续其执行完成CSocket
构造。 - 当工作线程访问 v-table 时,从“缓存”页面而不是包含正确 v-table 的真实内存中读取值。
乍一看,编译器没有插入内存屏障来避免这种情况。
我的假设是否正确?是否有可能发生或编译器/处理器有避免这种情况的机制?