ATL 7 + ATL_MIN_CRT в избранное  новое горячее всё    подписка   модер. 
От: Snax rsdnhttp://altergeo.ru/
Дата: 09.08.02 00:18
Оценка:48 (7)
Добрый день всем, кто не спал ночами, разбираясь, почему
при миграции с ATL3 на ATL7 программа начинает стреляться
в неожиданных местах, посвящается.

НЕ ИСПОЛЬЗУЙТЕ atlmincrt.lib, если не знаете что это
такое. Не знаете? Давайте посмотрим. Исходники MINCRT для
ATL находятся в папочке %InstDir%\Vc7\atlmfc\src\atl\atlmincrt
Берем, например, atlinit.cpp, функцию _atexit:

   nCurrentSize = _msize(__onexitbegin);
   [b]if((nCurrentSize+sizeof(_PVFV)) < ULONG(((const BYTE*)__onexitend-
      (const BYTE*)__onexitbegin)))[b]
   {
        //...
   }


сравниваем с аналогичной из страндартного CRT:

        if ( _msize_crt(__onexitbegin)
                < ((unsigned)((char *)__onexitend -
            (char *)__onexitbegin) + sizeof(_PVFV)) )
        {
            /*
             * not enough room, try to grow the table
             */
            //...
        }


Видите разницу? Нет? Разница в том, где находится + sizeof(_PVFV)
Стандартная CRT все делает правильно, а вот CRT из ATL7 прописывает
два указателя за пределами выделенной памяти.

Это пол-беды. Беда начнется, если произойдет еще один вызов _atexit().
Тут условие наконец-то станет истинным и произойдет вызов
::HeapRealloc(). А дальше как повезет. Возможно программа застрелится,
возможно, что застрелится, но по-позже. Да даже если менеджер кучи
позаботится о криворуких программистах из Редмонда и выделит памяти
на 8 байт больше, чем нужно, ::HeapRealloc(), если и сработает,
то на прописанные мимо 8 байт будут потеряны. Два деструктора
вызваны не будут. Ничего хорошего.

Павел.

P.S. У меня ::HeapRealloc() просто вызывает ::TerminateProcess() :crash:
Редкострое удовольствие было отыскивать эту ошибку ;)
Re: ATL 7 + ATL_MIN_CRT в избранное  новое    модер. 
От: Snax rsdnhttp://altergeo.ru/
Дата: 09.08.02 00:45
Оценка:3 (1)
В догонку: после вызова realloc() в функции atexit() стоит сохранить куда-нить
возвращаемое значение.


Правильная atexit():
int __cdecl atexit(_PVFV pf)
{
   size_t nCurrentSize;

   EnterCriticalSection(&g_csInit);

   if(__onexitbegin == NULL)
   {
      __onexitbegin = (_PVFV*)malloc(16*sizeof(_PVFV));
      if(__onexitbegin == NULL)
      {
         LeaveCriticalSection(&g_csInit);
         return(-1);
      }
      __onexitend = __onexitbegin;
   }

   nCurrentSize = _msize(__onexitbegin);
   if(nCurrentSize < ULONG(((const BYTE*)__onexitend-
      (const BYTE*)__onexitbegin)) + sizeof(_PVFV))
   {
      _PVFV* pNew;

      pNew = (_PVFV*)realloc(__onexitbegin, 2*nCurrentSize);
      if(pNew == NULL)
      {
         return(-1);
      }

      __onexitbegin = pNew;
   }

   *__onexitend = pf;
   __onexitend++;

   LeaveCriticalSection(&g_csInit);

   return(0);
}


с недоверием к ATL7,
Павел.
Re[2]: ATL 7 + ATL_MIN_CRT в избранное  новое    модер. 
От: Snax rsdnhttp://altergeo.ru/
Дата: 09.08.02 00:53
Подправить __onexitend[b] после вызова [b]realloc будет Вам
задачей на дом

с недоверием к ATL7,
Павел.
Re[3]: ATL 7 + ATL_MIN_CRT в избранное  новое    модер. 
От: Alex Fedotov rsdn 
Дата: 09.08.02 00:58
Здравствуйте Snax, Вы писали:

S>с недоверием к ATL7,

S>Павел.

То-то у меня стойкое подсознательное нежелание портировать текущий проект на ATL 7...
-- Alex Fedotov
Re: ATL 7 + ATL_MIN_CRT в избранное  новое    модер. 
От: raspopovhttp://www.cherubicsoft.com/
Дата: 12.08.02 04:31
Здравствуйте Snax, Вы писали:

S>Добрый день всем, кто не спал ночами, разбираясь, почему

S>при миграции с ATL3 на ATL7 программа начинает стреляться
S>в неожиданных местах, посвящается.

У меня стреляется и без использования min_crt. Причем не в моем коде, а где то в OLE32.DLL в районе функций маршалинга при работе с хипами в debug-версии. Поди разберись кто виноват, я, клиент или ATL.
Re[2]: ATL 7 + ATL_MIN_CRT в избранное  новое    модер. 
От: Snax rsdnhttp://altergeo.ru/
Дата: 12.08.02 05:03
Здравствуйте raspopov, Вы писали:

R>У меня стреляется и без использования min_crt. Причем не в моем коде, а где то в OLE32.DLL


А какие-нибудь ATL_DEBUG_QI не включены случайно? Если да, то это известная "фича":

Q272024


Павел.
Re[3]: ATL 7 + ATL_MIN_CRT в избранное  новое    модер. 
От: raspopovhttp://www.cherubicsoft.com/
Дата: 17.08.02 02:46
Здравствуйте Snax, Вы писали:

R>>У меня стреляется и без использования min_crt. Причем не в моем коде, а где то в OLE32.DLL

S>А какие-нибудь ATL_DEBUG_QI не включены случайно? Если да, то это известная "фича":
S>Q272024

Не-а, не она. Обычно вылетает в пределах RtlZeroHeap (правильно-то написал?), видимо куча где-то раньше кем-то ломается.