Освобождение памяти, выделенной массиву пустых указателей - PullRequest
3 голосов
/ 16 октября 2008

Я объявляю массив пустых указателей. Каждый из которых указывает на значение произвольного типа.
void **values; // Array of void pointers to each value of arbitary type

Инициализация значений следующим образом:


    values = (void**)calloc(3,sizeof(void*));
    //can initialize values as: values = new void* [3];
    int ival = 1;
    float fval = 2.0;
    char* str = "word";
    values[0] = (void*)new int(ival);
    values[1] = (void*)new float(fval);
    values[2] = (void*)str;

    //Trying to Clear the memory allocated
    free(*values); 
    //Error: *** glibc detected *** simpleSQL: free(): invalid pointer: 0x080611b4
    //Core dumped
    delete[] values*;
    //warning: deleting 'void*' is undefined
    //Similar Error.

Теперь, как мне освободить / удалить память, выделенную для значений (массив указателей void)?

Ответы [ 7 ]

7 голосов
/ 16 октября 2008

Я подозреваю, что проблема связана с тем, как вы выделили values: values = (void*)calloc(3,sizeof(void)). Это должно быть sizeof(void *), а не просто sizeof(void).

sizeof (void) может быть нулем или чем-то еще, что не имеет смысла, так что вы на самом деле не выделяете память для начала ... просто тупая удача, что назначения работают, и затем появляется ошибка попытаться освободить память.

РЕДАКТИРОВАТЬ: вы также напрашиваетесь на неприятности, чередуя C 101-style new / delete с C-style malloc / free. Можно использовать их обоих, если вы не delete что-то, что вы malloc 'ed или free что-то, что вы new' ed, но вы будете смешивать их в своей голове, если иди так.

6 голосов
/ 16 октября 2008

У вас есть 3 вещи, которые динамически распределяются и которые должны быть освобождены двумя различными способами:

delete reinterpret_cast<int*>( values[0]);    
delete reinterpret_cast<float*>( values[1]);

free( values); // I'm not sure why this would have failed in your example, 
               //    but it would have leaked the 2 items that you allocated 
               //    with new

Обратите внимание, что, поскольку str не выделен динамически, он не должен (фактически не может ) быть освобожден.

Пара заметок:

  • Я предполагаю, что sizeof(void) должен был быть sizeof(void*) поскольку то, что у вас есть, не будет компилироваться
  • Я не собираюсь ничего говорить о ваш, казалось бы, случайный кастинг, кроме что это похоже на код, который готов для стихийного бедствия в целом
4 голосов
/ 16 октября 2008

Это идеальная ситуация для повышения: любой класс
Также вы можете рассмотреть возможность использования вектора вместо выделения собственной памяти.

std::vector<boost::any>   data;
boost::any i1 = 1; // add integer
data.push_back(i1);

boost::any f1 = 1.0; // add double
data.push_back(f1);

data.push_back("PLOP"); // add a char *

std:: cout << boost::any_cast<int>(data[0]) + boost::any_cast<double>(data[1])
           << std::endl;

Возвращаясь к исходному коду, основная проблема была:

values = (void*)calloc(3,sizeof(void));

// This should  have been
void** values = (void**)calloc(3,sizeof(void*));

// Freeing the members needs care as you need to cast them
// back to the correct type before you release the memory.

// now you can free the array with
free(values);

Также обратите внимание: хотя использование новых / delete и calloc / free в одном и том же фрагменте кода не является противозаконным. Главным образом потому, что легко все перепутать, и это может привести к летальному исходу.

1 голос
/ 16 октября 2008

Вы смешиваете новое и * alloc (). Это нет-нет, и может привести к неопределенным результатам.

0 голосов
/ 16 октября 2008

Обратите внимание, что вы также не удаляете значения [0] и значения [1], что является утечкой памяти, но по своей конструкции вы не можете освобождать значения [2], так как это указатель на раздел .data.

0 голосов
/ 16 октября 2008

Я не уверен, почему вы используете new, если вы делаете что-то в C (ссылаясь на тег здесь).

Я бы выделил отдельные фрагменты массива, которые мне нужны, а затем освободил бы их, когда я закончил, я полагаю. Вы не можете освободить то, что не сделали сначала. Вы также не можете удалить пустой указатель.

0 голосов
/ 16 октября 2008

Вы должны будете отследить, сколько void * изначально было calloc'd, и перебрать их, освободив каждый, а затем освободив переменную исходных значений.

штопать форматирование ... (предварительный просмотр работает нормально).

int ct = 3;
values = (void*)calloc(ct,sizeof(void));
//can initialize values as: values = new void* [3];
int ival = 1;
float fval = 2.0;
char* str = "word";
values[0] = (void*)new int(ival);
values[1] = (void*)new float(fval);
values[2] = (void*)str;

for ( int i = 0; i < ct; i++ ) [
    delete( values[i] );
}
free( values );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...