Здравствуйте, Armastab, Вы писали:
A>Иногда (при указанной нагрузке 20 клиентов, в среднем раз в 30 секунд, иногда чаще, иногда реже), WSASend и WSARecv вываливаются с исключением 0x00000005 Access violation.
A>При этом поля класса pIOReq оказываются невалидными, как будто объект удален. Данное исключение выскакивает в отладчике и не перехватывается ни try-catch ни __try — __except
Вероятно в этот момент удалена структура CIOReq или сами буфера чтения/записи. Поскольку сама асинхронная операция в этот момент выполняется не в рабочем потоке процесса система выплевывает исключение которое не будет поймано. Или будет поймано "без стека", или вы увидите на экране "Приложение выполнило недопустимую операцию и будет закрыто", если отладки не было.
A>Экспериментально выяснилось, если количество рабочих потоков сделать равным 1 (обычно запущено 10), такой ошибки не возникает.
A>Если сделать защиту (собственный механизм) указателя pIOReq от удаления, до возврата из WSASend, WSARecv, то ошибки тоже не возникает, а отлавливается попытка удалить объект до снятия защиты.
Это потому что в одном потоке все вызовы будут сериализированы.
A>Из всего вышеописанного у меня сложилось ощущение, что один из ожидающих рабочих потоков получает управление и сигнал о завершении ввода-вывода, еще до того как произошел возврат из WSASend WSARecv.
A>Он удаляет объект pIOReq и в WSASend/WSARecv происходит нарушение доступа.
Тут сложно сказать наверняка, не видя кода, но это предположение скорее всего ошибочное.
A>Вопросы:
A>как сигнал о завершении ввода-вывода может поступать до завершения асинхронной функции ввода-вывода,
A>почему это исключение не отлавливается стандартными средствами обработки исключений
A>что с этим делать?
Отлаживать

Стоит подумать о счетчике ссылок в CIOReq (раз уж есть механизм защиты от его удаления)