Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > VariantCopy method is not threadsafe


Автор: voov 11.9.2008, 15:20
При копировании VARIANT получаю ошибку Access violation reading location.

В мсдн пишут, что VariantCopy method is not threadsafe. Мое приложение действительно многопоточное.
Кроме того, скомпилированая дэбаг версия запущеная отладчиком студии, работает нормально, а запущеная вне студии получает исключение Access violation reading location.

В чем именно опасность метода VariantCopy в многопоточном приложении и как устранить такую опасность?

Автор: Andrey44 12.9.2008, 08:42
voov, а может стоит попробовать memcpy или что-то в этом духе?

Автор: ama_kid 12.9.2008, 09:37
Цитата(voov @  11.9.2008,  16:20 Найти цитируемый пост)
В чем именно опасность метода VariantCopy в многопоточном приложении
VariantCopy - это не-атомарная операция, требует несколько шагов для своего выполнения, как минимум:
1) variant-приемник должен освободить свои ресурсы перед приёмом
2) должно произвестись копирование из источника в приёмник.
В многопоточном приложении теоретически возможно такое, что в приёмник присвоятся новые данные\ресурсы между освобождением старых и присвоением новых при копировании.

Автор: voov 12.9.2008, 10:26
Цитата(ama_kid @  12.9.2008,  09:37 Найти цитируемый пост)
В многопоточном приложении теоретически возможно такое, что в приёмник присвоятся новые данные\ресурсы между освобождением старых и присвоением новых при копировании. 

а как избежать такой ситуации? можно ли здесь както использовать CriticalSection или нужно по другому копировать?

Автор: voov 30.9.2008, 16:22
Следующий код:
Код

ItemData::ItemData( VARIANT & src ){
    VARIANT dst;
    dst.vt = VT_EMPTY;
    HRESULT result = VariantCopy( &dst, &src);
                ....
}

запущеный отладчиком студии (F5) работает без ошибок. Если запустить приложение вне студии (exe-файл из проводника, например), идут ошибки.

Сделал так: запустил приложение вне студии, сделал Attach to process... из студии и вижу такую штуку:
1. ошибки возникают только в том случае, если src содержит массив, но не всякий раз. некоторые вызовы, где src - массив, проходят успешно.
2. в случае возникновения ошибки result (E_INVALIDARG) показывает, что "Параметр задан неверно.". При этом портится src. Вместо safearray of R4 = [3](5.0000000,5.0000000,5.0000000)  (до вызова VariantCopy), он показывает safearray of R4 = [0]()  (после вызова VariantCopy) и т.п.

Получается, что во время выполнения VariantCopy, портится источник данных. Но как, где и почему портится непонятно. src создается перед вызовом этим же потоком и удаляется только после выполнения вышеуказаного кода
Код

typedef struct ITEMSTATE    {
    VARIANT vDataValue;
} ITEMSTATE;

.....
    ITEMSTATE *itemState = NULL;
    DWORD noItems = (DWORD)items.GetCount();

    HRESULT    result = iSychIO->Read(noItems, &itemState);    // СОМ интерфейс
    if (FAILED(result)){
        throw ...
    } 

    for (unsigned i = 0; i < noItems; i++){
        ItemData * data = NULL;
        data = new ItemData(itemState[i].vDataValue);    // здесь вариант должен скопироваться
    }

    iMalloc->Free(itemState);     // вот только здесь должен портиться источник данных


Попробую копировать вручную, но энтузиазма нет как и нет уверености, что поможет. Может кто-то все-таки может подсказать что-то  дельное?

Автор: voov 30.9.2008, 17:09
Вопрос снят.
Проблема была связана с освобождением памяти. Долго объяснять, скажу лишь, что ItemData это обертка для варианта, деструктор которой вызывает VariantClear. В одном месте я нашел лишний вызов VariantClear для данных из этой обертки. Из-за чего в деструкторе вызов VariantClear говорил что память заблокирована. 
После удаления лишнего вызова VariantClear ошибки прекратились.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)