В C / C ++ связанный список имеет только указатель заголовка, выделенный в стеке, и другие узлы, выделенные в куче. Это может вызвать утечку памяти? - PullRequest
1 голос
/ 20 ноября 2011

Для C и C ++ - связанный список с указателем, указывающим на его головной узел.Но все узлы размещаются в куче с помощью malloc () или new.Когда указатель заголовка выходит за пределы своей области, например, из функции выходит, все узлы, выделенные в куче, будут потеряны.Правильно?Это утечка памяти?

Как C / C ++ справляется с такой проблемой?Вызывает deallocator автоматически?(например, бесплатно () или удалить)?

Ответы [ 3 ]

1 голос
/ 20 ноября 2011

Лучший способ справиться с подобными вещами - использовать стандартный контейнер вместо какой-то домашней работы, если у вас нет веских причин и вы не знаете, что делаете и почему ...

станд :: вектор <>
станд :: Список <>

Но чтобы выбрать контейнер, важно знать, что вы делаете, какова продолжительность жизни.

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

Вы должны изменить свой подход к проблеме, чтобы воспринимать проблему как «объекты, выделенные вручную». Как только вы совершите этот скачок и поймете, что это плохой путь, вы можете выбирать между «они объектами значения» или «ими будет управлять shared_ptr».

EX1: использование shared_ptr для хранения новых объектов (этот подход следует использовать, если копирование вокруг MyNode - плохая идея [производительность, собственные ресурсы, сохраненное состояние]):

void MyFunction()
{
  typedef boost::shared_ptr<MyNode> NodePtr;
  std::list<NodePtr> my_list;
  my_list.push_back(NodePtr(new MyNode(args...)));
  my_list.push_back(NodePtr(new MyNode(args...)));
  ...
  // when this function exits, the nodes, which are owned by shared_ptr's
  // which are themselves owned by a stack instance of std::list<> 
  // will be automatically deleted, no leaks anywhere...
}

EX2: это то, что вы делаете, если ваши узлы дешевы, могут рассматриваться как копируемые объекты (семантика значений):

void MyFunction()
{
  std::vector<MyNode> my_list;
  my_list.push_back(MyNode(args...));
  my_list.push_back(MyNode(args...));
  ...
  // when this function exits, the nodes, which are shored directly as copies
  // in the vector container, will be automatically deleted, no leaks anywhere...
}

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

void MyFunction()
{
  std::list<MyNode*> my_list;
  my_list.push_back(new MyNode(args...));
  my_list.push_back(new MyNode(args...));
  ...
  // we must manually deallocate the nodes because nothing else has been given
  // responsibility anywhere (we're manually managing them)
  typedef std::list<MyNode*>::iterator iterator;
  for (iterator it = std::begin(my_list), end = std::end(my_list); it != end; ++it)
    delete *it;  // manually releases our allocated memory from the heap
  // the "head" is still deleted automatically because it is stack allocated
  // (the list object)
}
0 голосов
/ 20 ноября 2011

Да, это утечка памяти.Нет, ни C, ни C ++ (не существует такого языка, как C / C ++) не имеют никаких механизмов, чтобы справиться с этим.Они не JAVA или более поздний язык.Это зависит от ВАС, как от кодера.

0 голосов
/ 20 ноября 2011

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

...