#c #multithreading #com
#c #многопоточность #com
Вопрос:
У меня есть программа, которая также интенсивно использует потоки локальных ComQIPtr
переменных-членов ComQIPtr
, например (очень просто):
class dummy
{
public:
(some code)
void calledFromThreads ()
{
if (m_memberVar.getType()==1)
{
CComQIPtr<type2> localVar(m_memberVar);
(more code)
}
}
private:
CComQIPtr<type1> m_memberVar;
};
После интенсивного использования иногда в if (m_memberVar.getType()==1)
строке возникает исключение.
После отладки я вижу, что указатель указывает 0xdddddd (удаленная память), а после другого выполнения, поместив m_memberVar
точку останова памяти в позицию памяти, я вижу, что она освобождается при выходе из if (m_memberVar.getType()==1)
блока, при уничтожении CComQIPtr<type2> localVar(m_memberVar)
.
Это, ИМХО, никогда не должно происходить теоретически, потому что, когда CComQIPtr
создается, он уже создает AddRef
внутренне, поэтому, Release
когда CComQIPtr
уничтожается, это не должно влиять на него (это 1, а затем -1), даже если есть несколько одновременных обращений к одной и той же функции, всегда есть дополнениеперед вычитанием.
Но дело в том, что это происходит (время от времени и случайным образом) и в нескольких частях кода (он используется CComQIPtr
во многих частях), и я не понимаю, почему.
Комментарии:
1. Вы делаете некоторые предположения, которые могут быть или не быть верными: 1) COM-объект для начала правильно реализует пересчет, 2) у вас нет какой-либо другой ошибки в вашем коде, которая неожиданно перезаписывается
m_memberVar
случайным образом (переполнение буфера и т. Д.), 3)dummy
объект и, следовательно, егоm_memberVar
член, Неуничтожается во времяcalledFromThreads()
выполнения, таким образом, освобождаетсяm_memberVar
доCComQIPtr
того, как это возможноAddRef
.2. 1) Я предполагаю, что да, COM правильно реализует RefCount. 2) Я рассматривал эту возможность, но это не так: я проверил память, изменил положение объектов и т.д. 3) Объект активен в течение всего выполнения.
3. 1) пересчет осуществляют отдельные COM-объекты, а не сам COM. 2) итак, вы можете со 100% уверенностью проверить, что
type1*
удерживаемый указательm_memberVar
не изменяет значение при сбое? Потому что он не должен изменять значение, даже если базовыйtype
объект уничтожен. 3) если пересчет является точным иm_memberVar
не уничтожается или не повреждается, то то, что вы описываете, просто невозможно. Вам нужно будет поместить точку останова данных в удерживаемыйtype1*
указатель и посмотреть на стек вызовов, если / когда он действительно неожиданно изменит значение.4. Просматривая код, я вижу, что класс COM наследуется от CComSingleThreadModel вместо CComMultiThreadModel. Я думаю, что это будет проблемой…