Я думал об этом, крутя педали на работу. Один из возможных способов справиться с этим - сделать участки памяти доступными только для чтения, если к ним нет активного доступа и они не защищены из-за владения критическим разделом. Предполагается, что проблема вызвана записью потока в память, когда ему не принадлежит соответствующий критический раздел.
Есть довольно много ограничений, которые мешают ему работать. Наиболее важным является тот факт, что я думаю , что вы можете устанавливать привилегии только постранично (я считаю, 4K). Так что это, вероятно, потребует некоторых очень специфических изменений в вашей схеме распределения, чтобы вы могли сузить соответствующий раздел для защиты. Вторая проблема заключается в том, что он не будет ловить мошеннический поток, записывающий в память, если другой поток активно владеет критическим разделом. Но он поймал бы это и вызвал бы немедленное нарушение доступа, если бы критическая секция не принадлежала.
Идея состоит в том, чтобы изменить ваши вызовы EnterCriticalSection на:
EnterCriticalSection()
VirtualProtect( … PAGE_READWRITE … );
И измените вызовы LeaveCriticalSection на:
VirtualProtect( … PAGE_READONLY … );
LeaveCriticalSection()
В следующем фрагменте кода показан вызов VirtualProtect
int main( int argc, char* argv[] 1
{
unsigned char *mem;
int i;
DWORD dwOld;
// this assume 4K page size
mem = malloc( 4096 * 10 );
for ( i = 0; i < 10; i++ )
mem[i * 4096] = i;
// set the second page to be readonly. The allocation from malloc is
// not necessarily on a page boundary, but this will definitely be in
// the second page.
printf( "VirtualProtect res = %d\n",
VirtualProtect( mem + 4096,
1, // ends up setting entire page
PAGE_READONLY, &dwOld ));
// can still read it
for ( i = 1; i < 10; i++ )
printf( "%d ", mem[i*4096] );
printf( "\n" );
// Can write to all but the second page
for ( i = 0; i < 10; i++ )
if ( i != 1 ) // avoid second page which we made readonly
mem[i] = 1;
// this causes an access violation
mem[4096] = 1;
}