Распределение и освобождение памяти через границы dll - PullRequest
8 голосов
/ 28 августа 2009

Я понимаю, что выделение памяти, сделанное в одной dll, а затем free'd в другой, может вызвать все виды проблем, особенно в отношении CRT. Подобные проблемы особенно проблематичны при экспорте контейнеров STL. Мы сталкивались с подобными проблемами раньше (при написании пользовательских плагинов Adobe, связанных с нашими библиотеками), и мы решили эти проблемы, определив наш собственный распределитель, который мы используем во всех наших контейнерах, например:

typedef std::vector < SessionFields, 
        OurAllocator < SessionFields > > 
        VectorSessionFields;

typedef std::set < SessionFields, 
        std::less < SessionFields >, 
        OurAllocator < SessionFields > > 
        SetSessionFields;

Это хорошо сработало при передаче типов в / из нашего кода, однако мы столкнулись с проблемой в том, что теперь нам нужно вызвать функцию в SDK Adobe, которая возвращает заполненный вектор, который вызывает сбой при выходе из него области видимости.

Очевидно, это проблема с выделением памяти в SDK Adobe, принадлежащей другой куче, когда она, наконец, свободна в моем коде. Поэтому я думаю, что, возможно, я мог бы сделать что-то умное, например переопределить или экспортировать распределитель, используемый в их SDK, чтобы я мог использовать его для очистки контейнеров, возвращаемых из их функций.

Я также смотрю на написание оболочки или какого-то другого слоя, благодаря которому контейнеры STL будут безопасно размещаться между моим кодом и SDK (, хотя это звучит очень грязно ).

Кроме того, я также использую GetProcessHeaps для определения кучи, используемой в SDK, и пытаюсь освободиться от этой кучи вместо кучи по умолчанию.

У кого-нибудь есть советы, как мы можем решить эту проблему?

Ответы [ 3 ]

8 голосов
/ 28 августа 2009

Как ни странно, в Adobe Source Libraries есть класс adobe::capture_allocator, который был написан специально с учетом такого рода безопасности DLL. Он работает так, чтобы захватить локальные new и delete в этот момент, когда он создан, и переносить их обоих на время существования объекта. (См. adobe::new_delete_t для получения подробных сведений о том, как это происходит, особенно реализация здесь .) Распределение ресурсов выполняется с помощью захваченной процедуры delete, гарантирующей, что где бы вы ни находились удаляем с правильными delete.

Вы можете видеть capture_allocator, используемый в типах version_1 в исходных библиотеках Adobe, таких как adobe::any_regular_t и adobe::copy_on_write. capture_allocator должен быть совместим также со всеми типами контейнеров STL.

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

2 голосов
/ 28 августа 2009

В данный момент мы работаем над dll, который предоставляет функциональность C ++ через интерфейс C (ради того, чтобы C # мог использовать упомянутую dll).

например: dll имеет структуру myStruct_s, интерфейс предоставляет следующие функции:

interface.h

#ifndef INTERFACE_TYPES_H
# error Please include interace_types.h
#endif
    myStruct_s * CreateTheStruct() { return new myStruct_s(); }
    void DestroyTheStruct(myStruct_s * the_struct) { delete the_struct; }
    void DoSomethingToTheStruct(myStruct_s * the_struct);

interface_types.h

#define INTERFACE_TYPES_H
struct myStruct_s; // fwd declaration
#endif

interface.cpp

#if defined(__CPPPLUS) || defined(__cplusplus) || defined (__CPLUSPLUS)
#include<TheRealFileContainingTheRealMyStruct_s.h>
// handle the .h's functions here
#endif

comeOutsideCppFile.cpp

#include "interface_types.h"
#include "interface.h"

void main()
{
    myStuct_s * x = CreateTheStruct;
    DoSomethingToTheStruct(x);
    DestroyTheStruct(x);
}

Выше приведен примерный план того, как работает наш материал, в основном: Какими бы ни были разоблачения библиотеки DLL: Создано, Обработано, Уничтожено стороной DLL

Этот код не на 100% точен !!!

Также имейте в виду, что если вы используете чистую C ++ dll, вам, вероятно, понадобится тот же компилятор с теми же настройками, что и для сборки dll.

0 голосов
/ 28 августа 2009

Вы можете попытаться выяснить, существуют ли какие-либо формальные правила C ++ для того, что происходит, когда исключение генерируется в одной DLL и перехватывается в другой, а затем выходит из области видимости - это выглядит очень похоже. Для исключений, я думаю вы обязаны предоставить конструктору копирования специальную подпись, хотя сейчас я точно не знаю, что это такое.

...