I have an app crashing some times because the MS _purecall
is being called but the data I see on the crash dump is not what I expected.
I have CSocket
derived from CConnection
, the latter has a pure virtual function named DoRead
and the app crashes when an instance of CSocket
calls this function in a worker thread.
Following the register values and how Microsoft implements C++ virtual tables and calls, I see RCX
has the correct this
value, the first quad-word points to the v-table and the v-table is correct so the call to _purecall
should not happen.
But after seeing how the constructor is implemented, I see CConnection
constructor sets up the pointer to the v-table which includes the call to _purecall
and then, CSocket
's constructor overwrites this value with the correct/derived v-table.
This is what I suspect is happening:
- A thread calls to
new CSocket
. - Before
CSocket
constructor is called and the v-table modified, the worker thread reads some memory near the pointer (probably because it is processing an operation of otherCSocket
instance) and that memory page is "cached" by the processor. - The thread creating
CSocket
continues its execution finishingCSocket
construction. - When the worker thread accesses the v-table, reads the value from the "cached" page instead of the real memory containing the correct v-table.
At first glance there is no memory barrier inserted by the compiler to avoid this.
Am I correct in my assumption? Is it possible to happen or the compiler/processor has a mechanism to avoid this?