Утечка памяти с использованием shared_ptr

#c #shared-ptr

#c #shared-ptr

Вопрос:

Оба примера кода компилируются и выполняются без проблем. Использование второго варианта приводит к утечке памяти. Есть идеи, почему? Заранее спасибо за любую помощь.

Вариант 1:

 typedef boost::shared_ptr<ParameterTabelle&&t; SpParameterTabelle;

struct ParTabSpalteData
{
      ParTabSpalteData(const SpParameterTabelleamp; tabelle, const strin& id)
            :Tabelle(tabelle), Id(id)
      {

      }

      const SpParameterTabelleamp; Tabelle;
      strin& Id;
};
  

Вариант 2:

 struct ParTabSpalteData
{
      ParTabSpalteData(const SpParameterTabelleamp; tabelle, const strin& id)
            :Id(id)
      {
            // causes memory leak
            Tabelle2 = tabelle;
      }

      SpParameterTabelle Tabelle2;
      strin& Id;
};
  

Комментарии:

1. как вы определили, что есть утечка?

2. @Hassan: в моей IDE (Visual Studio 2008) обнаружена утечка памяти, показывающая адреса утекших областей памяти в консоли после завершения программы. Вывод на консоль утечки пропадает, если я использую первый вариант.

Ответ №1:

Вы проверили, что у вас нет циклических ссылок на общие указатели?

Например:

 class A {
  public: shared_ptr<A&&t; x;
};

shared_ptr<A&&t; a1(new A());
shared_ptr<A&&t; a2(new A());
a1-&&t;x = a2;
a2-&&t;x = a1;
  

Здесь a1 и a2 никогда не будут выпущены, потому что у них есть указатели друг на друга, которые поддерживают их работоспособность.

Итак, в вашем случае проверьте, SpParameterTabelle есть ли ссылка на ParTabSpalteData или есть ли другая возможность получить циклическую ссылку.

Комментарии:

1. Я думал, что это может быть такой проблемой. Но я думаю, что пример 1 должен демонстрировать такое же поведение, нет? или этого не произойдет, потому что это ссылка, а не сам shared_ptr ?

2. Да, я проверил и не смог найти никаких циклов. Я подумал, что, возможно, причиной проблемы является присвоение const shared_ptramp; shared_ptr в конструкторе второго варианта, но не могу найти объяснения…

3. Используя constamp; в указателе, shared_ptr не увеличивает количество использований. Если вы создаете копию, как в случае 2, это происходит. Так что, вероятно, где-то есть цикл…

4. @nabulke Возможно, вам следует попытаться воссоздать минимальный экземпляр проблемы, чтобы мы могли ее скомпилировать?

5. Эмпирическое правило Я предполагаю, что использование ссылки или указателя интеллектуального указателя подрывает назначение указанного интеллектуального указателя

Ответ №2:

Обратите внимание, что передача интеллектуального указателя как const SpParameterTabelleamp; tabelle не запрещает вам изменять объект pointee.

Вы пробовали передавать интеллектуальный указатель напрямую, как

 struct ParTabSpalteData
{
      ParTabSpalteData(SpParameterTabelle tabelle, const strin& id)
            :Tabelle2(tabelle), Id(id)
      {
      }

      SpParameterTabelle Tabelle2;
      strin& Id;
};
  

Ответ №3:

Выведите что-нибудь в деструкторе ParameterTabelle (trace/fileout) или установите там точку останова. Это действительно не вызывается дважды?

Недавно я обновил проект VS2005 до VS2010, и внезапно VS2010 сообщил об утечках памяти в boost::lexical_cast . И не во всех из них, только в одном модуле в одной строке — в этом файле были даже другие lexical_cast того же типа / другие типы повсюду.

Даже тесты состояния локальной памяти сообщили об этом как об утечке памяти (код только для режима отладки):

 void run_stream_tests(std::ofstreamamp; out)
{
#ifdef _DEBUG
  CMemoryState preState;
  preState.Checkpoint();
#endif
  {
    ...your code...
  }
#ifdef _DEBUG
  CMemoryState postState;
  postState.Checkpoint();
  CMemoryState diffState;
  if( diffState.Difference( preState, postState ) )
  {
    TRACE("Memory leaked!n");
    preState.DumpAllObjectsSince();
  }
#endif
}
  

Таким образом, это также может быть проблемой VS2010 / VS2008.

Комментарии:

1. Спасибо за ваш вклад. Учитывая это, я буду использовать Boundschecker или Purify, чтобы получить второе мнение относительно утечек памяти.

Ответ №4:

Также существует вероятность того, что обнаружение утечки памяти Visual Studio является ошибочным.