Как я могу предотвратить инкапсуляцию одного и того же неуправляемого указателя в два разных SafeHandles?

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

Как я могу предотвратить это эффективно? Я сомневаюсь, что маршаллер автоматически отслеживает дубликаты...

2 ответа

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

  1. Вы можете использовать счетчики ссылок - вы в основном ведете счетчик количества дескрипторов, содержащих конкретный указатель и операторы перегрузки (в C используют вызовы функций вместо назначений), чтобы обновить счетчики назначений. Вы освобождаете указатель только после того, как счетчик достиг 0, Этот подход, хотя и точный, имеет значительные накладные расходы, а также подвержен циклам и, следовательно, может утечь память. Это модель собственности подсчета ссылок.

  2. Вы можете создать unique_ptr, Что это в основном означает, что в любое время только 1 дескриптор содержит ссылку на определенный указатель. Это означает, что если вы делаете что-то вроде -

    a = b 
    

    Указатель будет скопирован из b в a а также b автоматически станет недействительным (скорее контракт API, а не реализация). Это означает, что пользователь должен построить код вокруг этих ограничений. Здесь освобождение делается, когда любой объект, содержащий ссылку, выходит из области видимости. Это эксклюзивная модель владения.

Есть и другие подходы (например, weak_ptr) и вы можете прочитать о них в любой справке C++.

Хотя этот ответ был на другой вопрос, он будет работать в этом случае.

Я мог бы создать фабричный класс, который будет вызывать для меня управляемые функции, а затем создать SafeHandles вручную в ограниченной области выполнения, как это делает marhsaller. Этот фабричный класс может отслеживать неуправляемые указатели и, если SafeHandle уже был создан, вернуть его вместо создания нового.

Другие вопросы по тегам