0

我的应用程序有时会崩溃,因为_purecall正在调用 MS,但我在故障转储中看到的数据不是我所期望的。

CSocket派生自CConnection,后者有一个名为的纯虚函数DoRead,当一个实例CSocket在工作线程中调用此函数时,应用程序崩溃。

根据寄存器值以及 Microsoft 如何实现 C++ 虚拟表和调用,我看到RCX了正确的this值,第一个四字指向 v-table 并且 v-table 是正确的,因此_purecall不应发生调用。

但是在看到构造函数是如何实现的之后,我看到CConnection构造函数设置了指向 v-table 的指针,其中包括调用_purecall然后,CSocket的构造函数用正确/派生的 v-table 覆盖这个值。

这就是我怀疑正在发生的事情:

  1. 一个线程调用new CSocket.
  2. CSocket调用构造函数和修改 v-table 之前,工作线程读取指针附近的一些内存(可能是因为它正在处理其他CSocket实例的操作)并且该内存页面被处理器“缓存”。
  3. 线程创建CSocket继续其执行完成CSocket构造。
  4. 当工作线程访问 v-table 时,从“缓存”页面而不是包含正确 v-table 的真实内存中读取值。

乍一看,编译器没有插入内存屏障来避免这种情况。

我的假设是否正确?是否有可能发生或编译器/处理器有避免这种情况的机制?

4

0 回答 0