#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 является ошибочным.