Как вы смотрите на глобальные объекты в .dll? Интересует вот что — где для вас находится граница, определяющая, объекты каких именно классов можно создавать в .dll со static storage duration в случае линковки с CRT? Вот недавно, например, узнал, что библиотека zeromq, необходимая мне для межпроцессного взаимодействия, к числу безопасных не относится — виснет на WaitForSingleObject. Теперь вообще задумываюсь над тем, чтобы убрать глобальные std::unique_ptr и std::string из .dll — мало ли что и когда там появится...
То, что глобальные объекты — это плохо в целом, я знаю. Интересует конкретная ситуация с .dll
Да, кто не в курсе — для глобальных объектов в .dll в случае линковки с CRT выдвигаются те же требования, что и к DllMain
If your DLL is linked with the C run-time library (CRT), the entry point provided by the CRT calls the constructors and destructors for global and static C++ objects. Therefore, these restrictions for DllMain also apply to constructors and destructors and any code that is called from them.
Здравствуйте, Nikita.Trophimov, Вы писали:
NT>Да, кто не в курсе — для глобальных объектов в .dll в случае линковки с CRT выдвигаются те же требования, что и к DllMain
А вы собирайте проект без CRT, RTTI и т.п. Классы при этом можно юзать свободно (в этом случае я предпочитаю STLPort).
NT>>Да, кто не в курсе — для глобальных объектов в .dll в случае линковки с CRT выдвигаются те же требования, что и к DllMain M>А вы собирайте проект без CRT, RTTI и т.п. Классы при этом можно юзать свободно (в этом случае я предпочитаю STLPort).
глобальные объекты без CRT свободно юзать несколько эээ.. затруднительно
Как много веселых ребят, и все делают велосипед...
M>А вы собирайте проект без CRT, RTTI и т.п. Классы при этом можно юзать свободно (в этом случае я предпочитаю STLPort).
Что тогда с моей стороны мне придётся сделать? Определить собственную точку входа, самостоятельно вызывать конструкторы и деструкторы для объектов со static storage duration, etc?
глобальные объекты без CRT свободно юзать несколько эээ.. затруднительно
лично я бы сказал что при достаточном уровне знаний — элементарно. и можно делать это где угодно — хоть в длл, хоть в драйвере.
для начала неплохо было бы почитать это и конечно посмотреть \vc\crt\src файлы.
дальше решение может быть например такое
ну и в начале (exeentry, dllmain, driverentry) вызвать initterm(), при выходе destroyterm () (если надо) MAX_DESTRUCTOR_COUNT определяю по необходимости...
A>
//поскипана куча непортабельных хаков A>
A>ну и в начале (exeentry, dllmain, driverentry) вызвать initterm(), при выходе destroyterm () (если надо) MAX_DESTRUCTOR_COUNT определяю по необходимости...
это и есть "затруднительно". Ну и опять же если вы будете вызывать эту байду в dllmain — получите ровно теми самыми граблями по лбу, что и в случае использования CRT. Причем в этом случае они даже не будут прикрыты листиками.
Как много веселых ребят, и все делают велосипед...
NT>Что тогда с моей стороны мне придётся сделать? Определить собственную точку входа, самостоятельно вызывать конструкторы и деструкторы для объектов со static storage duration, etc?
ну да, причем от CRT избавляцца вовсе не обязательно. Указываете в настройках линкера свою специательную SpecialDllMain в качестве entry point'а, в ней ничего не делаете (возвращаете TRUE) в ответ на PROCESS ATTACH/DETACH. объявляете в коде прототип CRT'шной точки входа:
и вызываете его ручками с DLL_PROCESS_ATTACH/DETACH в безопасные моменты. Главное как говорицца — вовремя вынуть. В висте с этим может помочь FlsAlloc. Ну или безопаснее всего — все ручками, ручками.. DLL_THREAD_ATTACH/DETACH мона (и даже нуна) дергать напрямую из SpecialDllMain. Разумеется если был уже дернут PROCESS_ATTACH
Как много веселых ребят, и все делают велосипед...
Здравствуйте, ononim, Вы писали:
A>> O>//поскипана куча непортабельных хаков A>>
A>>ну и в начале (exeentry, dllmain, driverentry) вызвать initterm(), при выходе destroyterm () (если надо) MAX_DESTRUCTOR_COUNT определяю по необходимости...
O>это и есть "затруднительно". Ну и опять же если вы будете вызывать эту байду в dllmain — получите ровно теми самыми граблями по лбу, что и в случае использования CRT. Причем в этом случае они даже не будут прикрыты листиками.
ну незнаю. лично я использую это уже несколько лет и всё прекрасно работает, никаких граблей или проблем.
непортабельных хаков
незнаю где здесь хаки, а по поводу непортабельных-пока используешь microsoft cl.exe + linker.exe — всё впорядке. ничего другого мне не надо
с CRT главная проблема на мой взгляд — это версии, то что используемая версия может просто быть не установлена на клиетской машине — то есть сначала нужно инсталлировать необходимую тебе версию.. а с другой стороны зачем CRT вообще нужна... сугубо моя личная точка зрения — когда достигаешь некого уровня знаний/умений — необходимость в CRT полностью отпадает
A>>>ну и в начале (exeentry, dllmain, driverentry) вызвать initterm(), при выходе destroyterm () (если надо) MAX_DESTRUCTOR_COUNT определяю по необходимости... O>>это и есть "затруднительно". Ну и опять же если вы будете вызывать эту байду в dllmain — получите ровно теми самыми граблями по лбу, что и в случае использования CRT. Причем в этом случае они даже не будут прикрыты листиками. A>ну незнаю. лично я использую это уже несколько лет и всё прекрасно работает, никаких граблей или проблем.
ну со статиками проблема ТС в том что их конструкторы/деструкторы вызываются из DllMain'а, а у DllMain'а есть некоторые ограничения
A>сугубо моя личная точка зрения — когда достигаешь некого уровня знаний/умений — необходимость в CRT полностью отпадает
это пройдет
Как много веселых ребят, и все делают велосипед...
KA>А в чем проблема то ? Боишся что в конструкторе может оказатся чтото типа LoadLibrary ?
Почему именно LoadLibrary? Любые небезопасные с точки зрения DllMain функции. В документации сказано, что полный список безопасных функций из Kernel32.dll, к сожалению, достать не получится. А откуда я могу знать, что позовут конструкторы объектов каких-либо сторонних библиотек? Даже если я посмотрю в исходный код, то где гарантия, что в следующей версии они его не поменяют?
Because Kernel32.dll is guaranteed to be loaded in the process address space when the entry-point function is called, calling functions in Kernel32.dll does not result in the DLL being used before its initialization code has been executed. Therefore, the entry-point function can call functions in Kernel32.dll that do not load other DLLs. For example, DllMain can create synchronization objects such as critical sections and mutexes, and use TLS. Unfortunately, there is not a comprehensive list of safe functions in Kernel32.dll.