Таинственные глобальные переменные - COM / STA Apartment Object - PullRequest
1 голос
/ 30 марта 2011

Вот сценарий:

-COM DLL, загруженная в адресное пространство процесса, использующего DLL.-Внутри пары DLL существуют глобальные переменные (скажем, var a, var b) и глобальная функция.-Процесс запускается, вызывает глобальную функцию и инициализирует глобальные переменные a, b и вызывает CoInitialize (NULL) - Поток является STA.-Тогда эта же глобальная функция создает COM-объект STA

Позже в программе тот же поток (поток, который вызвал CoInitialize выше и создал COM-объект STA) вызывает ту же глобальную C-функцию (давайте назовем ее func ())в этой DLL.В области действия C-функции состояние глобальных переменных точно такое же, как и ожидалось (т.е. правильно инициализировано).В ту минуту, когда функция func () вызывает метод COM для существующего COM-объекта STA, объект COM, находящийся в одной и той же DLL, видит совершенно разные копии глобальных переменных (var a, var b).Я взял адрес обеих переменных, и они полностью различаются в C-функции, в отличие от вызываемой функции COM-объектов.Что здесь происходит?Я думал, что глобалы в одном и том же адресном пространстве должны быть видны по всей доске.

1 Ответ

1 голос
/ 30 марта 2011

Возможно, загружаются два экземпляра вашей DLL - один явно приложением, в котором размещена ваша DLL, а второй - через подсистему COM через CoCreateInstance. Первый будет искать в пути поиска DLL процесс приложения, а второй будет искать в реестре местоположение COM-компонента, который реализует ваш COCLASS.

Если в вашей DLL есть DllMain (или функция InitInstance, если это DLL на основе MFC), то вы можете установить точку останова и посмотреть на аргумент hinstance (или AfxGetInstanceHandle, если MFC), чтобы увидеть, если (a) вы инициализируете дважды и (б) вы видите два разных дескриптора экземпляра DLL. Если так, то вы определенно загружаетесь дважды.

Расположение DLL в файловой системе имеет значение, поэтому вы должны посмотреть, есть ли копии в отдельных местах, которые могут быть отдельно загружены на основе правил, которые я упоминал выше.

Как правило, COM DLL никогда не загружается напрямую. Вы должны разбить свою функциональность на две библиотеки DLL с библиотекой COM-сервера, выделенной для работы с COM. Вы можете предоставить себе внутренний интерфейс COCLASS, который позволит вам передавать ваши глобальные переменные в COM DLL, если вы того пожелаете.

...