Re[8]: Проблема с высвобождением памяти в dll
От: anton20vlad  
Дата: 11.03.09 17:13
Оценка:
Здравствуйте, A.Lokotkov, Вы писали:

AL>Здравствуйте, anton20vlad, Вы писали:


A>>Проблема решилась VirtualAlloc, VirtualFree. Всё красиво и тихо отрабатывает. Только вот не уверен что это правильное решение )


AL>Как именно оно решилось?


DIVA_STATUS DLL_SPEC WDIVA_getRequestInfo(RequestInfo *reqInf, int reqNum)
{
                
   DIVA_REQUEST_INFO* requestInfo = (DIVA_REQUEST_INFO *)VirtualAlloc(NULL,sizeof(DIVA_REQUEST_INFO),MEM_COMMIT,PAGE_READWRITE);
   DIVA_STATUS cr = DIVA_getRequestInfo (
                    reqNum,
                    requestInfo
                    );
    
    if (cr == DIVA_OK) 
    {
      reqInf->progress = requestInfo->progress;
      reqInf->requestType = requestInfo->requestType;
      reqInf->requestState = requestInfo->requestState;
      reqInf->abortionCode = DIVA_AR_NONE;

      if (requestInfo->requestState == DIVA_ABORTED || requestInfo->requestState == DIVA_PARTIALLY_ABORTED) 
      {
          reqInf->abortionCode = requestInfo->abortionReason.code; 
                        
      }
                    
    }
   VirtualFree(requestInfo,0,MEM_RELEASE);

   return cr;             

}


Никаких ошибок с памятью, отрабатывает как надо.
Re[9]: Проблема с высвобождением памяти в dll
От: A.Lokotkov Россия  
Дата: 11.03.09 17:25
Оценка:
Здравствуйте, anton20vlad, Вы писали:

A>Никаких ошибок с памятью, отрабатывает как надо.


Вы можете рассказать, почему Вы сделали именно так и почему оно перестало падать?
bloß it hudla
Re[10]: Проблема с высвобождением памяти в dll
От: anton20vlad  
Дата: 11.03.09 17:28
Оценка:
Здравствуйте, A.Lokotkov, Вы писали:

AL>Здравствуйте, anton20vlad, Вы писали:


A>>Никаких ошибок с памятью, отрабатывает как надо.


AL>Вы можете рассказать, почему Вы сделали именно так и почему оно перестало падать?



Перебирал варианты ) и сделал так. А вот насчёт почему перестало падать...думаю что решился вопрос с тем где именно и кем выделяется и высвобождается память. Вы видите какую-то ошибку в коде?
Re[11]: Проблема с высвобождением памяти в dll
От: A.Lokotkov Россия  
Дата: 11.03.09 17:54
Оценка:
Здравствуйте, anton20vlad, Вы писали:

A>Перебирал варианты ) и сделал так. А вот насчёт почему перестало падать...думаю что решился вопрос с тем где именно и кем выделяется и высвобождается память. Вы видите какую-то ошибку в коде?


Конструктор и деструктор интерфейсного объекта на клиентской стороне теперь не вызываются. Поскольку не вызывается конструктор, для каждой stl-строки внутри интерфейсного объекта DIVA_REQUEST_INFO не создается небольшой умолчательный буфер, -- там будет NULL. Когда несконструированный интерфейсный объект с несконструированными строками внутри передается в их dll, stl почему-то не падает. Может быть, потому что, увидев NULL, аллокирует буфера в строках на стороне dll. Если это так, то после того, как Вы делаете VirtualFree на своей стороне, память, выделенная под буфера строк, никогда не будет освобождена (по-крайней мере, до выгрузки выделившей ее dll). Для такого решения необязательно делать именно VirualAlloc/VirualFree, я думаю, с тем же успехом можно было бы написать как-нибудь так:

DIVA_STATUS DLL_SPEC WDIVA_getRequestInfo(RequestInfo *reqInf, int reqNum)
{
  __int64 placement[sizeof(DIVA_REQUEST_INFO) + sizeof(__int64) - 1];
  memset(placement, 0, (sizeof(DIVA_REQUEST_INFO) + sizeof(__int64) - 1));
  DIVA_REQUEST_INFO* requestInfo = reinterpret_cast<DIVA_REQUEST_INFO*>(placement);
  DIVA_STATUS cr = DIVA_getRequestInfo (reqNum, requestInfo);
  //...
  return cr;             
}
bloß it hudla
Re: Проблема с высвобождением памяти в dll
От: g_i  
Дата: 11.03.09 18:45
Оценка:
Здравствуйте, anton20vlad, Вы писали:

Динамический рантайм мог бы спасти отца русской демократии
Re[2]: Проблема с высвобождением памяти в dll
От: MasterZiv СССР  
Дата: 11.03.09 22:05
Оценка: -1
g_i пишет:

> Динамический рантайм мог бы спасти отца русской демократии


у него он и так динамический. Другого не бывает в .dll.
Posted via RSDN NNTP Server 2.1 beta
Re[3]: Проблема с высвобождением памяти в dll
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 12.03.09 04:10
Оценка:
Здравствуйте, MasterZiv, Вы писали:

>> Динамический рантайм мог бы спасти отца русской демократии

MZ>у него он и так динамический. Другого не бывает в .dll.

/MT для при сборке .dll уже отменили?
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Re[3]: Проблема с высвобождением памяти в dll
От: g_i  
Дата: 12.03.09 05:43
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>g_i пишет:


>> Динамический рантайм мог бы спасти отца русской демократии


MZ>у него он и так динамический. Другого не бывает в .dll.


Судя по описанию проблемы, это не так.
Re[12]: Проблема с высвобождением памяти в dll
От: Аноним  
Дата: 12.03.09 07:34
Оценка:
Здравствуйте, A.Lokotkov, Вы писали:

AL>
AL>DIVA_STATUS DLL_SPEC WDIVA_getRequestInfo(RequestInfo *reqInf, int reqNum)
AL>{
AL>  __int64 placement[sizeof(DIVA_REQUEST_INFO) + sizeof(__int64) - 1];
AL>  memset(placement, 0, (sizeof(DIVA_REQUEST_INFO) + sizeof(__int64) - 1));
AL>  DIVA_REQUEST_INFO* requestInfo = reinterpret_cast<DIVA_REQUEST_INFO*>(placement);
AL>  DIVA_STATUS cr = DIVA_getRequestInfo (reqNum, requestInfo);
AL>  //...
AL>  return cr;             
AL>}
AL>





Да, действительно так тоже работает без ошибок. Мне всё-таки важно, чтобы память занятая строками высвобождалась. Признаюсь, что настолько глубоко я темой не владею, поэтому хочу спросить Вашего совета. Мне предложили ещё несколько способов(цитирую):

Мне кажется самое простое это 3й вариант. Правда как я понимаю, память всё-равно не высвободится, так как деструктор пустой? И ещё один вопрос: для чего нужно "подмутить методы-аксесоры"? Это я недопонял.
Re[4]: Проблема с высвобождением памяти в dll
От: anton20vlad  
Дата: 12.03.09 07:37
Оценка:
Здравствуйте, Odi$$ey, Вы писали:

OE>Здравствуйте, MasterZiv, Вы писали:


>>> Динамический рантайм мог бы спасти отца русской демократии

MZ>>у него он и так динамический. Другого не бывает в .dll.

OE>/MT для при сборке .dll уже отменили?



/MT при сборке имеется.
Re[4]: Проблема с высвобождением памяти в dll
От: MasterZiv СССР  
Дата: 12.03.09 07:46
Оценка:
g_i пишет:

> MZ>у него он и так динамический. Другого не бывает в .dll.

>
> Судя по описанию проблемы, это не так.

Тем хуже для него. Так может только в этом и проблема ?
А вообще, какой рантайм "Дельфа" использует ?
Posted via RSDN NNTP Server 2.1 beta
Re[12]: Проблема с высвобождением памяти в dll
От: anton20vlad  
Дата: 12.03.09 07:49
Оценка:
Здравствуйте, A.Lokotkov

В продолжение темы с пустым деструктором и про "подмутить методы аксесоры". Судя по всему, их таки надо подмутить так как ошибка никуда не делась...Правда я не понимаю что имеется в виду.
Re[13]: Проблема с высвобождением памяти в dll
От: A.Lokotkov Россия  
Дата: 12.03.09 08:52
Оценка:
Здравствуйте, Аноним, Вы писали:

А>[/list]


А>Мне кажется самое простое это 3й вариант. Правда как я понимаю, память всё-равно не высвободится, так как деструктор пустой? И ещё один вопрос: для чего нужно "подмутить методы-аксесоры"? Это я недопонял.


Я не понял, что коллеги имели в виду. Для того, чтобы все работало правильно, у авторов из DLL должны были быть экспортированы конструктор и деструктор интерфейсного объекта DIVA_REQUEST_INFO. Тогда проблем бы не было вообще (ну, вернее, были бы, но они решались бы путем добровольного запрета на доступ к строковым членам из клиента по записи), поскольку при любом способе создания объекта DIVA_REQUEST_INFO на клиентской стороне (по new, на стеке или статически) буферы stl-строк и прочая создавались бы и освобождались в их DLL.
Авторы DLL этого не сделали, поэтому конструктор и деструктор DIVA_REQUEST_INFO, сгенерированные компилятором, всегда вызываются на клиентской стороне и, конструктор, как минимум, создает в каждой stl-строке маленький исходный буфер. А это значит, что у проблемы нет корректного решения, есть только костыли разной степени кривизны типа такого (эскиз, предполагающий, что обертка для delphi также расположена в dll):

// Используется для всех запросов к той DLL
// При необходимости использования из разных потоков
// дооснастить крит.секцией.
static DIVA_REQUEST_INFO* globalRequestor = NULL;

BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved )
{
    switch (ul_reason_for_call)
    {
      case DLL_PROCESS_ATTACH:
      {
        globalRequestor = (DIVA_REQUEST_INFO*) new [sizeof(DIVA_REQUEST_INFO) + sizeof(__int64) - 1];
        // В этом случае все аллокации stl-строк будут всегда выполняться на стороне их DLL,
        // и память не потечет.
        if(globalRequestor != NULL)
          memset(globalRequestor, 0, (sizeof(DIVA_REQUEST_INFO) + sizeof(__int64) - 1));
      }
      break;
      case DLL_PROCESS_DETACH:
      {
        // в принципе, не очень-то и нужно
        if(globalRequestor != NULL)
          delete [] globalRequestor;
      }
          break;
    }
    return TRUE;
}

DIVA_STATUS DLL_SPEC WDIVA_getRequestInfo(RequestInfo *reqInf, int reqNum)
{
  // передаем глобальный интерфейсный объект
  DIVA_STATUS cr = DIVA_getRequestInfo (reqNum, globalRequestor);
  //...
  return cr;             
}


У меня больше нет идей.
bloß it hudla
Re[5]: Проблема с высвобождением памяти в dll
От: Danchik Украина  
Дата: 12.03.09 11:25
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>g_i пишет:


>> MZ>у него он и так динамический. Другого не бывает в .dll.

>>
>> Судя по описанию проблемы, это не так.

MZ>Тем хуже для него. Так может только в этом и проблема ?

MZ>А вообще, какой рантайм "Дельфа" использует ?

Тут до Delphi еще далеко, он CPP не может заставить работать.
Re[5]: Проблема с высвобождением памяти в dll
От: g_i  
Дата: 12.03.09 12:04
Оценка:
Здравствуйте, anton20vlad, Вы писали:

A>Здравствуйте, Odi$$ey, Вы писали:


OE>>Здравствуйте, MasterZiv, Вы писали:


>>>> Динамический рантайм мог бы спасти отца русской демократии

MZ>>>у него он и так динамический. Другого не бывает в .dll.

OE>>/MT для при сборке .dll уже отменили?



A>/MT при сборке имеется.


У вас имеется dll. С каким рантаймом собрана эта dll? Со статическим? Заказать пересборку с динамическим можно?
Важно чтобы оба модуля (клиент и длл) использовали один тип рантайма. Затем важно чтобы они могли работать с одной и той-же версией рантайм dll.
Re[6]: Проблема с высвобождением памяти в dll
От: g_i  
Дата: 12.03.09 12:08
Оценка:
Здравствуйте, g_i, Вы писали:

Сам себя запутал.
DLL собираешь ты. Используй динамический рантайм если клиент сможет использовать динамический рантайм.
Если нет — не используй string. Вообще, откуда проблема с деструктором std::string если ты утверждаешь, что допустимы только сишные экспорты?
Re[3]: Проблема с высвобождением памяти в dll
От: alsemm Россия  
Дата: 12.03.09 12:41
Оценка:
Здравствуйте, anton20vlad, Вы писали:

A>Спасибо, за ответ. У меня нет вариантов — так сваяли библиотеку апишную буржуи. Я честно говоря уже все мозги сломал как решить эту проблему? Да я понимаю что оно в разных местах выделяется и высвобождается, но в этом конкретном случае что нужно сделать чтобы избавится от ошибки?

Я правильно понимаю, что, проблема состоит только в том, что приложение валится, когда дело доходит до разрушения локальной DIVA_REQUEST_INFO requestInfo; внутри WDIVA_getRequestInfo()?
Ваша обертка и буржуйский код используют совместимые версии STL, т.е. строки в структуре requestInfo инициализирются корректно?
Если все так, то можно так попробовать проблему решить:
DIVA_STATUS DLL_SPEC WDIVA_getRequestInfo(int RequestType, int reqNum)
{
    static char requestInfoBuffer[sizeof(DIVA_REQUEST_INFO)] = { 0 };

    DIVA_REQUEST_INFO* pRequestInfo = (DIVA_REQUEST_INFO*)&requestInfoBuffer;

    DIVA_STATUS cr = DIVA_getRequestInfo (reqNum, pRequestInfo);
    return 1;
}


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

Если у вас приложение многопоточное, то вместо простого глобального статического буфера можно использовать буфер из TLS.

Алексей
Re[6]: Проблема с высвобождением памяти в dll
От: MasterZiv СССР  
Дата: 12.03.09 16:37
Оценка: -2
g_i пишет:

> У вас имеется dll. С каким рантаймом собрана эта dll? Со статическим?

> Заказать пересборку с динамическим можно?

Если какая-то DLL собрана со статическим рантаймом, то её, за исключением очень
редких случаев очень грамотного проектирования интерфейсов этой .DLL,
которые в жизни почти не встречаются, и к числу которых данная .DLL явно НЕ
относится, МОЖНО СРАЗУ ЖЕ ВЫКИНУТЬ НА ПОМОЙКУ, как непригодную к использованию.
Posted via RSDN NNTP Server 2.1 beta
Re[6]: Проблема с высвобождением памяти в dll
От: MasterZiv СССР  
Дата: 12.03.09 16:39
Оценка:
Danchik пишет:

> Тут до Delphi еще далеко, он CPP не может заставить работать.


Да я вообще не очень понимаю, что он там делать собирается,
как он это дело в дельфу вставит ? Легче наверное новый язык
программирования изучить, чем это вот сделать.
Posted via RSDN NNTP Server 2.1 beta
Re[7]: Проблема с высвобождением памяти в dll
От: Odi$$ey Россия http://malgarr.blogspot.com/
Дата: 13.03.09 04:09
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>Если какая-то DLL собрана со статическим рантаймом, то её, за исключением очень

MZ>редких случаев очень грамотного проектирования интерфейсов этой .DLL,
MZ>которые в жизни почти не встречаются, и к числу которых данная .DLL явно НЕ
MZ>относится, МОЖНО СРАЗУ ЖЕ ВЫКИНУТЬ НА ПОМОЙКУ, как непригодную к использованию.

обосновать можешь?
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.