В этом примере, конечно, имеет смысл воспользоваться
классом типа CScopeLock.
Кроме того, случается, что ::EnterCriticalSection()
вызывается без инициализации критической секции с помощью
::InitializeCriticalSection(). Особенно часто такое случается с проектами, написанными с помощью ATL. Причем в debug-версии все работает замечательно, а
release-версия рушится. Это происходит из-за так называемой "минимальной"
CRT (_ATL_MIN_CRT), которая не вызывает конструкторы статических объектов
(Q166480, Q165076). В ATL версии 7.0 эту проблему решили.
Еще я встречал такую ошибку: программист пользовался
классом типа CScopeLock, но для экономии места называл эту переменную одной буквой:
и как-то раз просто пропустил имя у переменной.
Получилось
Что это означает? Компилятор честно сделал вызов
конструктора CScopeLock и тут же уничтожил этот безымянный объект, как и
положено по стандарту. Т.е. сразу же после вызова метода Lock() последовал
вызов Unlock(), и синхронизация перестала иметь место. Вообще, давать
переменным, даже локальным, имена из одной буквы – путь быстрого наступления на
всяческие грабли.
СОВЕТ
Если у вас в процедуре больше одного
цикла, то вместо int i,j,k стоит все-таки использовать что-то вроде int
nObject, nSection, nRow.
|
Архитектурные ошибки
Самая известная из них – это взаимоблокировка
(deadlock), когда две нити пытаются захватить две или более критических секций, причем делают это в разном порядке.
Листинг
10. Взаимоблокировка двух ниток.