освободить память для двойного указателя

//char char **p; declared in .h file
size_t bs = 5;
size_t Size = sizeof(obj);
p = (char**)malloc(bs);
for (size_t i = 0; i < bs;i++){p[i] = (char*)malloc(Size);}

for (size_t j = 0; j < bs-1; j ++){p[j] = &(p[j + 1][0]); }

for (size_t i = 0; i < bs; i++){free(p[i]);}

free(p);

мой код зависает при попытке освободить последний элемент p в цикле for. Кто-нибудь, что я могу делать неправильно?

РЕДАКТИРОВАТЬ: у меня все еще есть та же проблема, даже когда я меняю ее на (char*)malloc(bs sizeof(char *));

это все еще не работает:

size_t bs = 5;
size_t Size = sizeof(obj);
p = (char**)malloc(bs* sizeof(char *));
for (size_t i = 0; i < bs;i++){p[i] = (char*)malloc(Size);}
for (size_t j = 0; j < bs-1; j ++){p[j] = &(p[j + 1][0]); }
for (size_t i = 0; i < bs; i++){free(p[i]);}
free(p);

использование new вместо malloc также не решает проблему

Однако этот код отлично освобождает память.

size_t bs = 5;
size_t Size = sizeof(obj);
p = (char**)malloc(bs* sizeof(char *));
for (size_t i = 0; i < bs;i++){p[i] = (char*)malloc(Size);}
for (size_t i = 0; i < bs; i++){free(p[i]);}
free(p);

так что проблема, кажется, что-то с этим фрагментом кода

for(size_t j = 0; j < bs-1; j ++){p[j] = &(p[j + 1][0]); }

Я хочу, чтобы это был неявный связанный список, кто-нибудь знает, что я делаю неправильно?


person user3233447    schedule 24.01.2014    source источник
comment
Зачем использовать тег C++ при использовании malloc?   -  person Ed Heal    schedule 25.01.2014
comment
Это С или С++? Я предполагаю, что это действительно в любом случае, но, возможно, выберите только один.   -  person zero298    schedule 25.01.2014
comment
возможный дубликат освобождения двойного указателя   -  person zero298    schedule 25.01.2014
comment
Вы понимаете, что &(pool[j + 1][0]) точно такое же, как pool[j + 1]?   -  person Ben Voigt    schedule 25.01.2014
comment
@Ed: индекс итерации объявляется в скобках for; это похоже на функцию С++ для меня. (это было добавлено в более поздних версиях C?   -  person Ben Voigt    schedule 25.01.2014
comment
В C: не приводить результат malloc. Но в C++ вам нужно это сделать.   -  person pzaenger    schedule 25.01.2014
comment
@pzaenger - вы вообще не используете malloc   -  person Ed Heal    schedule 25.01.2014
comment
@BenVoigt - насколько мне известно, он уже довольно давно является частью C.   -  person Ed Heal    schedule 25.01.2014
comment
@EdHeal: Да, я знаю. Но ОП использовал malloc, поэтому я написал это :)   -  person pzaenger    schedule 25.01.2014
comment
@Ed: В C++ вы используете malloc, если вы передаете что-то в API, для которого требуются данные malloc (потому что он будет использовать free). Программисты на C++ должны знать основы использования std::malloc   -  person Ben Voigt    schedule 25.01.2014
comment
@BenVoigt - В наши дни это очень неприятный случай. Во всяком случае, это не подразумевается в ОП. Итак, предполагается, что это не C++   -  person Ed Heal    schedule 25.01.2014


Ответы (3)


Вы не выделяете достаточно места для указателей. Изменить на

p = malloc(bs * sizeof(char*));
person cup    schedule 24.01.2014
comment
Это одна из причин, почему C++ лучше. Было бы выделено надлежащее количество с new. - person Mark Ransom; 25.01.2014
comment
@Mark: я думаю, вы хотели сказать, почему оператор new[] C++ лучше? malloc работает точно так же в C++, и функции выделения C++, такие как ::operator new(), также требуют количества байтов. - person Ben Voigt; 25.01.2014

В первом malloc вам нужно не 5 байт, а 5 указателей.

p = (char**)malloc(bs * sizeof(char *));
person deviantfan    schedule 24.01.2014
comment
Хорошо, я изменил его на (char**)malloc(bs * sizeof(char *)); это все еще дает мне ту же проблему. - person user3233447; 25.01.2014
comment
Это верно, но слово утечка для этого не подходит. На самом деле это переполнение, потому что доступны элементы за концом. - person Ben Voigt; 25.01.2014
comment
Технически утечка — это когда вы забыли что-то освободить. Вы определили проблему, но дали ей неправильное название. - person Mark Ransom; 25.01.2014

Проблема в том, что вы:

  • выделить массив из 5 указателей
  • выделить 5 массивов символов и сохранить их в этом первом массиве
  • переместите эти указатели вниз в массиве, перезаписав (и потеряв) первый указатель и продублировав последний
  • попытаться освободить 5 указателей в массиве.

Таким образом, на этом последнем шаге вы дважды освобождаете указатель (поскольку последние две записи в p[3] и p[4] одинаковы), что приводит к неопределенному поведению.

Вы говорите, что вам нужен «неявный связанный список», подразумевая, что вы пытаетесь вставить указатели в объекты (а не в массив верхнего уровня, как вы делаете), и в этом случае вы хотите что-то вроде:

for(size_t j = 0; j < bs-1; j ++) { *(char **)p[j] = p[j + 1]); }
*(char **)p[bs-1] = 0;  // null terminate the linked list

это предполагает, что obj определено примерно так:

struct obj {
    struct obj *next;
    // more fields
person Chris Dodd    schedule 24.01.2014