Как я могу предотвратить инкапсуляцию одного и того же неуправляемого указателя в два разных SafeHandles?
Я пишу управляемую оболочку для игрового движка, написанного на C, чтобы испытать себя. Я начал оборачивать неуправляемые указатели в SafeHandle
производные, но это на меня возложило, что вызовы неуправляемых функций, которые могут вернуть тот же указатель, вероятно, создадут новые SafeHandles, и если одна из них будет удалена, остальные станут недействительными.
Как я могу предотвратить это эффективно? Я сомневаюсь, что маршаллер автоматически отслеживает дубликаты...
2 ответа
Вы пытаетесь решить проблему, на которую пытаются ответить большинство управляемых указателей и методов сбора мусора. В зависимости от варианта использования, есть несколько решений для этого -
Вы можете использовать счетчики ссылок - вы в основном ведете счетчик количества дескрипторов, содержащих конкретный указатель и операторы перегрузки (в C используют вызовы функций вместо назначений), чтобы обновить счетчики назначений. Вы освобождаете указатель только после того, как счетчик достиг
0
, Этот подход, хотя и точный, имеет значительные накладные расходы, а также подвержен циклам и, следовательно, может утечь память. Это модель собственности подсчета ссылок.Вы можете создать
unique_ptr
, Что это в основном означает, что в любое время только 1 дескриптор содержит ссылку на определенный указатель. Это означает, что если вы делаете что-то вроде -a = b
Указатель будет скопирован из
b
вa
а такжеb
автоматически станет недействительным (скорее контракт API, а не реализация). Это означает, что пользователь должен построить код вокруг этих ограничений. Здесь освобождение делается, когда любой объект, содержащий ссылку, выходит из области видимости. Это эксклюзивная модель владения.
Есть и другие подходы (например, weak_ptr
) и вы можете прочитать о них в любой справке C++.
Хотя этот ответ был на другой вопрос, он будет работать в этом случае.
Я мог бы создать фабричный класс, который будет вызывать для меня управляемые функции, а затем создать SafeHandles вручную в ограниченной области выполнения, как это делает marhsaller. Этот фабричный класс может отслеживать неуправляемые указатели и, если SafeHandle уже был создан, вернуть его вместо создания нового.