Удаление динамической памяти, указанной статическим указателем

У меня есть следующая структура (упрощенно):

class myType
{
static char* data;
//more private data here
public:
//public interface here
};

data это ресурс, общий для всех экземпляров myType и это указывает на динамически распределенную память (выделенную одним из экземпляров после инициализации).

Все идет нормально. Проблема возникает, когда мне нужно освободить память, указанную data, Подсчет ссылок здесь не является решением, потому что это допустимая и возможная ситуация, когда нет ни одного экземпляра myType в какой-то момент выполнения — и позже может быть создан новый экземпляр — таким образом data должен сохраняться.

Мне нужно освободить эту память при выгрузке драйвера, но выгрузка не связана с фактическим уничтожением myType объекты, поэтому я вынужден освободить data вручную. Это было бы приемлемо, но data есть (и должно быть) private и недоступный из обработчика выгрузки. Конечно, я могу создать static а также public destroy функция внутри myType но это не кажется правильным — в конце концов мне не нужно public инициализатор, так зачем мне нужен один, чтобы освободить память? Эти данные не должны быть доступны извне myType экземпляров.

Я буду признателен за любые идеи по этому вопросу.

2

Решение

В зависимости от сложности вашего кода я бы предпочел один из двух вариантов:

  1. Иметь статическую публику destroyMetadata метод, который необходимо вызывать, если во время выполнения были созданы какие-либо экземпляры. Лично я не вижу ничего особенно плохого в том, чтобы иметь метод уничтожения неявно созданных данных. Проблема с этим подходом состоит только в том, что это ручной подход и, следовательно, несколько ошибочный
  2. Создайте (одиночный) Unload-Handler, где вы можете зарегистрировать обратные вызовы, которые будут выполняться при очистке. Тогда вы можете сделать свой destroyMetadata частный статический метод и зарегистрируйте его с помощью обработчика, когда data впервые создан. Это немного больше усилий, но в целом дает более чистый дизайн.

Какой из этих двух вариантов подходит вам, зависит от того, насколько сложной может стать ваша очистка. Если у вас есть десятки классов с пользовательской очисткой, второй вариант кажется предпочтительным, поскольку он обеспечивает лучшую инкапсуляцию и более чистый код в целом. Однако, если это единственная часть вашего кода, где вам нужна такая очистка, будет немного сложно написать такой обобщенный обработчик (YAGNI), поэтому первый подход, хотя и концептуально более сложный, выглядит намного лучше в этом сценарии.

3

Другие решения

Отсутствие необходимости в общедоступном инициализаторе для его выделения не имеет значения для его освобождения — тривиально выделить его при первом использовании, потому что вы запускаете код, который знает, что он должен быть (если (data == NULL) data = new. …), но если это не имеет смысла в вашем деструкторе, тогда может потребоваться публичный освобождение, если вы хотите гарантировать возврат памяти.

Другая возможность (если это имеет смысл в вашем случае) — это подсчет ссылок, увеличенный в вашем конструкторе и уменьшенный в вашем деструкторе, но когда счет достигнет нуля, немедленно не освобождать. Вместо этого вы можете установить таймер для освобождения после определенного периода «охлаждения». Если конструктор (или другой код, который лениво выделяет память) вызывается до того, как этот таймер сработает, вы отменяете таймер вместо перераспределения, но если таймер срабатывает, он освобождает.

1

Я не понимаю, почему public static Функция уничтожения не будет выглядеть правильно. Как вы утверждаете, нет никакой связи между требуемым моментом разрушения и временем жизни объекта и его экземплярами. Таким образом, вы возлагаете ответственность за своевременное уничтожение на внешнюю сущность, которая затем должна иметь логический доступ к ней. public static подход имеет больше смысла в этом случае. Это своего рода тонкий сборщик мусора.

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

1
По вопросам рекламы [email protected]