Нахождение повышения:: shared_ptr циклические ссылки

Есть ли какие-либо подсказки/приемы для нахождения циклических ссылок shared_ptr?

Это - экс-клен того, что я пытаюсь найти - к сожалению, я, может казаться, не нахожу цикл в своем коде.

struct A
{
  boost::shared_ptr<C> anC;
};

struct B
{
  boost::shared_ptr<A> anA;
};

struct C
{
  boost::shared_ptr<B> anB;
};
9
задан Zac 5 January 2010 в 01:21
поделиться

6 ответов

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

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

1
ответ дан 4 December 2019 в 21:10
поделиться

Однажды я отвечал за разработку системы кредитного риска (на языке С++, хотя это не относится к делу). Это действительно большие графики с распределением риска по узлам. У нас была простая эвристика, чтобы выяснить, были ли мы в цикле - если мы проехали более 500 раз (я забыл точную цифру - она была настраиваемой), то ответ был "да". Большинство схем обнаружения циклов полагаются на эвристику вроде этой.

3
ответ дан 4 December 2019 в 21:10
поделиться

В прошлом у меня были похожие проблемы - утечки памяти из-за циклических ссылок shared_ptr, которые оставались незамеченными в течение нескольких месяцев.

Следите за "кэшами". У меня есть объект (назовем его "Factory"), который обрабатывал элементы ("Виджет"). Виджеты имели свойство быть A) Неизменяемыми, а B) Имели shared_ptr к своему создателю (он иногда создавал другие виджеты и т.д.). Все работало отлично, пока я не добавил кэш виджетов на Factory - так как виджеты были неизменяемыми, имело смысл кэшировать их, возвращать один и тот же виджет обратно каждый раз, когда он запрашивался. Мой кэш был кэшем shared_ptr, так что мгновенная бесшумная утечка. Исправления очевидны, поэтому я не буду вдаваться в них.

В конце концов, я смог опереться на платформу, которую использовал для обнаружения таких утечек памяти из CRT. В CRT Visual Studio есть обнаружение утечек памяти и составление отчетов, которые я включил в свою тестовую программу для предотвращения регрессий:

int main()
{
    // code code code
    // code code code

#ifdef _MSC_VER
    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
    _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
    _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
    _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
    _CrtDumpMemoryLeaks();
#endif
}

GCC, вероятно, имеет похожие базовые отчеты об утечках, но я не знаю, что это такое.

.
1
ответ дан 4 December 2019 в 21:10
поделиться

Можно реализовать некий отладочный интерфейс, возвращающий список share_ptrs, принадлежащих этому объекту. Это нужно будет сделать для каждого класса, хранящегося в shared_ptr. Теперь у вас есть общий граф, который можно обойти, и на нем можно использовать алгоритмы определения циклов. Думаю Алгоритм сильно связанных компонент Тарьяна мог бы подойти для этого, но теория графов - это не мое состояние.

.
0
ответ дан 4 December 2019 в 21:10
поделиться

Я бы порекомендовал использовать Valgrind . Когда вы закроете процесс, он покажет вам всю утечку памяти. Если выключение как-то не прерывает цикл, то любые циклы должны отображаться как утечка памяти, и Valgrind скажет вам, откуда в вашем коде изначально была выделена память.

5
ответ дан 4 December 2019 в 21:10
поделиться

Я думаю, что самый простой ответ заключается в том, что есть только столько умных указателей, которые могут сделать для вас:

Я предлагаю записывать всякий раз, когда вы делаете цикл, (легко, если вы создаете все три объекта одновременно, в противном случае ...), а затем проверять ту запись, где вы удаляете / развязываете объекты, или просто периодически, если это не возможно.

0
ответ дан 4 December 2019 в 21:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: