Как работает подсчет ссылок интеллектуального указателя с подсчетом ссылок?

StackOverflow https://stackoverflow.com/questions/725142

Вопрос

Другими словами, как реализация отслеживает подсчет?

Поддерживается ли объект, похожий на карту, доступный всем shared_ptr экземпляры, ключом которых является адрес указателя, а значением — количество ссылок?Если мне нужно реализовать shared_ptr, это первая идея, которая приходит мне в голову.

Существует ли вероятность утечки памяти в случае этих интеллектуальных указателей с подсчетом ссылок?Если да, то как мне их избежать?

Это было полезно?

Решение

Я видел два разных ненавязчивых подхода к этому:

  1. Умный указатель выделяет небольшой блок памяти, чтобы содержать эталонный счетчик.Каждая копия Smart Pointer затем получает указатель на фактический объект и указатель на количество ссылок.
  2. В дополнение к указателю объекта, каждый умный указатель содержит предыдущий и следующий указатель, тем самым образуя дважды связанный список интеллектуальных указателей с определенным объектом.Подсчет ссылок подразумевается в списке.Когда умный указатель копируется, он добавляет себя в список.После разрушения каждый умный указатель удаляется из списка.Если это последний в списке, он также освобождает ссылочный объект.

Если вы идете здесь и прокрутите вниз, там есть отличная диаграмма, которая гораздо более четко объясняет эти методы.

Другие советы

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

Каждый объект интеллектуального указателя содержит общий счетчик ссылок — по одному для каждого необработанного указателя.

Вы могли бы взглянуть на этот статья.Эта реализация сохраняет их в отдельном объекте, который копируется.Вы также можете взглянуть на документация boost или взгляните на Статья в Википедии на умных указателях.

Нет.shared_ptr просто сохранит один дополнительный указатель для подсчета ссылок.

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

Насколько я помню, в главе «Эффективный C++» рассматривалась проблема указателя подсчёта ссылок.

В принципе, у вас есть «легкий» класс указателя, содержащий указатель на класс, содержащий ссылку, который знает, как увеличивать/уменьшать ссылку и уничтожать объект указателя.Этот класс подсчета ссылок указывает на объект, на который осуществляется ссылка.

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

Самый простой способ утечки памяти с помощью указателей с подсчетом ссылок — создание циклов.Например, двусвязный список, в котором все указатели имеют значениеshared_ptr как минимум с двумя элементами, гарантированно не будет удален.Даже если внешние указатели будут освобождены, внутренние указатели все равно будут учитываться, а счетчик ссылок не достигнет 0.По крайней мере, при самой наивной реализации.

Самое простое решение проблемы цикличности — это смешиваниеshared_ptr (указателей с подсчетом ссылок) со слабыми указателями, которые не разделяют право собственности на объект.

Общие указатели будут совместно использовать как ресурс (указатель), так и дополнительную информацию reference_count.Когда вы используете слабые указатели, счетчик ссылок удваивается:существует счетчик ссылок на общий указатель и счетчик ссылок на слабый указатель.Ресурс освобождается всякий раз, когда счетчик общих указателей достигает 0, но информация reference_count остается активной до тех пор, пока не будет освобожден последний слабый указатель.

В двусвязном списке внешняя ссылка хранится в файлеshared_ptr, а внутренние ссылки — в файлеweak_ptr.Всякий раз, когда внешние ссылки (shared_ptr) отсутствуют, элементы списка освобождаются, удаляя слабые ссылки.В конце все слабые ссылки будут удалены, и последний слабый указатель на каждый ресурс освобождает информацию reference_count.

Это менее запутанно, чем кажется в приведенном выше тексте...Я попробую еще раз позже.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top