Утечка памяти в C - PullRequest
       33

Утечка памяти в C

2 голосов
/ 27 ноября 2009

Я новичок в C и пишу очень простой связанный список. Мне интересно, будет ли утечка памяти в следующем коде:

void removeListEntry(struct tableEntry *symp, struct tableEntry *previous) {
  if (symp->next = 0){
    symbolList.tail = previous;
    previous->next =0;
  } else {
    previous->next = symp->next;
    symp->next = 0;
  }
}

Я почти уверен, что если указатель symp не сохранен в другой переменной, нет способа получить доступ к записи списка, на которую указывает указатель, поэтому у меня будет утечка памяти. В C мы используем функцию malloc () для выделения пространства памяти для структуры данных, и я помню, как использовал ключевое слово new для «динамического» выделения памяти в C ++. Каковы различия между распределением памяти с помощью malloc () и использованием new? В моем коде действительно есть утечка памяти?

Ответы [ 4 ]

5 голосов
/ 27 ноября 2009
if (symp->next = 0) {

Это if- «условие» является назначением, настройка symp->next на 0. Если указатель на другой объект был сохранен в symp->next, этот объект будет потерян, и память объектов не будет освобождена.

Для сравнения вам нужно использовать == вместо:

if (symp->next == 0) {

или сделайте это без явного сравнения:

if (!symp->next) {

В случае else вы удаляете symp из списка (предполагая, что previous действительно содержит элемент перед symp), но вы не освобождаете его память. Это может быть утечка памяти, но это зависит от кода, вызывающего функцию: этот код может все еще освобождать symp или делать что-то еще с удаленным элементом, или он может просто забыть об этом и потерять свою память.

1 голос
/ 27 ноября 2009

Мне любопытно, что должно происходить в вашем коде:

if (symp->next = 0){
  symbolList.tail = previous;
  previous->next =0;
} else {
  previous->next = symp->next;
  symp->next = 0;
}

Когда symb->next не будет нулем? Вы ничего не делаете, если symb пусто, поскольку головной узел также будет нулевым.

Запутанная часть заключается в том, что вы добавляете previous к symb в первом if (что всегда должно быть так), но в следующем вы добавляете symb к previous. Каково обоснование для этого второго, и в каком случае это когда-либо случится?

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

symb->next = 0, вероятно, является просто опечаткой, как указывалось, поскольку это всегда будет правдой, и это частая ошибка. То, что я начал делать, чтобы помочь поймать это, это сделать: if (0 == symb->next), так что если вы сделали 0=symb->next, вы получите ошибку компилятора.

UPDATE:

Как было указано в комментарии, эта функция всегда будет переходить к предложению 'else', что на самом деле может быть ожидаемым поведением.

1 голос
/ 27 ноября 2009

Вам нужно позвонить free(), как только вы закончили использовать память, выделенную на malloc().

0 голосов
/ 27 ноября 2009

Как указано выше if(symp->next = 0) является операцией присваивания, и оператор if будет иметь значение false. Из-за этого вы не только потеряете указатель на следующую запись таблицы после symp, но вы также потеряете предыдущий-> следующий указатель (который, я полагаю, указывает на symp в любом случае?).

Просто вопрос стиля, но лично я переписал бы функцию, чтобы она была такой:

void removeNextListEntry(struct tableEntry *previous) {
  struct tableEntry *dummy = previous->next;
  if (dummy->next == 0){
    symbolList.tail = previous;
    previous->next =0;
  } else {
    previous->next = dummy->next;
  }
  free(dummy);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...