Глобальные объекты в .dll
От: Nikita.Trophimov  
Дата: 08.04.13 16:01
Оценка:
Как вы смотрите на глобальные объекты в .dll? Интересует вот что — где для вас находится граница, определяющая, объекты каких именно классов можно создавать в .dll со static storage duration в случае линковки с CRT? Вот недавно, например, узнал, что библиотека zeromq, необходимая мне для межпроцессного взаимодействия, к числу безопасных не относится — виснет на WaitForSingleObject. Теперь вообще задумываюсь над тем, чтобы убрать глобальные std::unique_ptr и std::string из .dll — мало ли что и когда там появится...

То, что глобальные объекты — это плохо в целом, я знаю. Интересует конкретная ситуация с .dll

Да, кто не в курсе — для глобальных объектов в .dll в случае линковки с CRT выдвигаются те же требования, что и к DllMain

http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583%28v=vs.85%29.aspx

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.

Re: Глобальные объекты в .dll
От: meto Россия  
Дата: 08.04.13 18:45
Оценка:
Здравствуйте, Nikita.Trophimov, Вы писали:

NT>Да, кто не в курсе — для глобальных объектов в .dll в случае линковки с CRT выдвигаются те же требования, что и к DllMain


А вы собирайте проект без CRT, RTTI и т.п. Классы при этом можно юзать свободно (в этом случае я предпочитаю STLPort).
Re[2]: Глобальные объекты в .dll
От: ononim  
Дата: 09.04.13 10:57
Оценка:
NT>>Да, кто не в курсе — для глобальных объектов в .dll в случае линковки с CRT выдвигаются те же требования, что и к DllMain
M>А вы собирайте проект без CRT, RTTI и т.п. Классы при этом можно юзать свободно (в этом случае я предпочитаю STLPort).
глобальные объекты без CRT свободно юзать несколько эээ.. затруднительно
Как много веселых ребят, и все делают велосипед...
Re[2]: Глобальные объекты в .dll
От: Nikita.Trophimov  
Дата: 09.04.13 18:10
Оценка:
M>А вы собирайте проект без CRT, RTTI и т.п. Классы при этом можно юзать свободно (в этом случае я предпочитаю STLPort).

Что тогда с моей стороны мне придётся сделать? Определить собственную точку входа, самостоятельно вызывать конструкторы и деструкторы для объектов со static storage duration, etc?
Re[3]: Глобальные объекты в .dll
От: anonymous185  
Дата: 09.04.13 19:02
Оценка: 1 (1)
Здравствуйте, ononim, Вы писали:

глобальные объекты без CRT свободно юзать несколько эээ.. затруднительно


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

#pragma comment(linker, "/merge:.CRT=.rdata")

typedef void (__cdecl *PF)(void);

#pragma const_seg(".CRT$XCA")
const PF __xc_a = 0;
#pragma const_seg(".CRT$XCZ")
const PF __xc_z = 0;
#pragma const_seg()

#ifdef MAX_DESTRUCTOR_COUNT

int cxpf;
PF pfx[MAX_DESTRUCTOR_COUNT];

extern "C" int __cdecl atexit(PF func)
{
  pfx[cxpf++] = func;
  return 0;
}

void destroyterm () 
{
  while (cxpf--) (pfx[cxpf])();
}

#endif//MAX_DESTRUCTOR_COUNT

void initterm()
{
  const PF * ppf = &__xc_a; 
  while (ppf < &__xc_z)
  {
    PF pf = *ppf++;
    if (pf) pf();
  }
}

ну и в начале (exeentry, dllmain, driverentry) вызвать initterm(), при выходе destroyterm () (если надо) MAX_DESTRUCTOR_COUNT определяю по необходимости...
Re[4]: Глобальные объекты в .dll
От: ononim  
Дата: 09.04.13 22:31
Оценка:
A>
//поскипана куча непортабельных хаков
A>

A>ну и в начале (exeentry, dllmain, driverentry) вызвать initterm(), при выходе destroyterm () (если надо) MAX_DESTRUCTOR_COUNT определяю по необходимости...


это и есть "затруднительно". Ну и опять же если вы будете вызывать эту байду в dllmain — получите ровно теми самыми граблями по лбу, что и в случае использования CRT. Причем в этом случае они даже не будут прикрыты листиками.
Как много веселых ребят, и все делают велосипед...
Re[3]: Глобальные объекты в .dll
От: ononim  
Дата: 09.04.13 22:47
Оценка:
NT>Что тогда с моей стороны мне придётся сделать? Определить собственную точку входа, самостоятельно вызывать конструкторы и деструкторы для объектов со static storage duration, etc?
ну да, причем от CRT избавляцца вовсе не обязательно. Указываете в настройках линкера свою специательную SpecialDllMain в качестве entry point'а, в ней ничего не делаете (возвращаете TRUE) в ответ на PROCESS ATTACH/DETACH. объявляете в коде прототип CRT'шной точки входа:
extern "C" 
{
BOOL WINAPI _DllMainCRTStartup(
        HANDLE  hDllHandle,
        DWORD   dwReason,
        LPVOID  lpreserved
        );
}

и вызываете его ручками с DLL_PROCESS_ATTACH/DETACH в безопасные моменты. Главное как говорицца — вовремя вынуть. В висте с этим может помочь FlsAlloc. Ну или безопаснее всего — все ручками, ручками.. DLL_THREAD_ATTACH/DETACH мона (и даже нуна) дергать напрямую из SpecialDllMain. Разумеется если был уже дернут PROCESS_ATTACH
Как много веселых ребят, и все делают велосипед...
Re: Глобальные объекты в .dll
От: Kubyshev Andrey  
Дата: 10.04.13 03:48
Оценка:
А в чем проблема то ? Боишся что в конструкторе может оказатся чтото типа LoadLibrary ?
Комент может написать на видном месте для коллег и все ?
Re[5]: Глобальные объекты в .dll
От: anonymous185  
Дата: 10.04.13 07:26
Оценка: :)
Здравствуйте, ononim, Вы писали:

A>>

O>//поскипана куча непортабельных хаков
A>>

A>>ну и в начале (exeentry, dllmain, driverentry) вызвать initterm(), при выходе destroyterm () (если надо) MAX_DESTRUCTOR_COUNT определяю по необходимости...


O>это и есть "затруднительно". Ну и опять же если вы будете вызывать эту байду в dllmain — получите ровно теми самыми граблями по лбу, что и в случае использования CRT. Причем в этом случае они даже не будут прикрыты листиками.


ну незнаю. лично я использую это уже несколько лет и всё прекрасно работает, никаких граблей или проблем.

непортабельных хаков

незнаю где здесь хаки, а по поводу непортабельных-пока используешь microsoft cl.exe + linker.exe — всё впорядке. ничего другого мне не надо
с CRT главная проблема на мой взгляд — это версии, то что используемая версия может просто быть не установлена на клиетской машине — то есть сначала нужно инсталлировать необходимую тебе версию.. а с другой стороны зачем CRT вообще нужна... сугубо моя личная точка зрения — когда достигаешь некого уровня знаний/умений — необходимость в CRT полностью отпадает
Re[6]: Глобальные объекты в .dll
От: ononim  
Дата: 10.04.13 08:56
Оценка:
A>>>ну и в начале (exeentry, dllmain, driverentry) вызвать initterm(), при выходе destroyterm () (если надо) MAX_DESTRUCTOR_COUNT определяю по необходимости...
O>>это и есть "затруднительно". Ну и опять же если вы будете вызывать эту байду в dllmain — получите ровно теми самыми граблями по лбу, что и в случае использования CRT. Причем в этом случае они даже не будут прикрыты листиками.
A>ну незнаю. лично я использую это уже несколько лет и всё прекрасно работает, никаких граблей или проблем.
ну со статиками проблема ТС в том что их конструкторы/деструкторы вызываются из DllMain'а, а у DllMain'а есть некоторые ограничения

A>сугубо моя личная точка зрения — когда достигаешь некого уровня знаний/умений — необходимость в CRT полностью отпадает

это пройдет
Как много веселых ребят, и все делают велосипед...
Re[2]: Глобальные объекты в .dll
От: Nikita.Trophimov  
Дата: 10.04.13 16:43
Оценка:
KA>А в чем проблема то ? Боишся что в конструкторе может оказатся чтото типа LoadLibrary ?

Почему именно LoadLibrary? Любые небезопасные с точки зрения DllMain функции. В документации сказано, что полный список безопасных функций из Kernel32.dll, к сожалению, достать не получится. А откуда я могу знать, что позовут конструкторы объектов каких-либо сторонних библиотек? Даже если я посмотрю в исходный код, то где гарантия, что в следующей версии они его не поменяют?

http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583%28v=vs.85%29.aspx

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.

 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.