Как мне удалить этот указатель Void?

#c #memory-management #void-pointers

#c #управление памятью #указатели void

Вопрос:

 #define ALIGNBUF(Length) Length % ALIGNSIZE ? 
              Length   ALIGNSIZE - (Length % ALIGNSIZE) : Length 

short NumCols;
long * ColLenArray, * OffsetArray;

ColLenArray = new long(NumCols * sizeof(long));
OffsetArray = new long(NumCols * sizeof(long));

// THIS CODE SHOULD NOT BE NEEDED TO UNDERSTAND THE PROBLEM
// BUT I HAVE INCLUDED IT JUST IN CASE
////////////////////////////////////////////////////////////
SQLColAttribute(hstmt, ((SQLUSMALLINT) i) 1, SQL_DESC_OCTET_LENGTH, NULL, 0, NULL, amp;ColLenArray[i]);
    ColLenArray[i] = ALIGNBUF(ColLenArray[i]);
    if (i)
        OffsetArray[i] = OffsetArray[i-1] ColLenArray[i-1] ALIGNBUF(sizeof(SQLINTEGER));
////////////////////////////////////////////////////////////

void **DataPtr = new void*[OffsetArray[NumCols - 1]   ColLenArray[NumCols - 1]   ALIGNBUF(sizeof(long))];

delete []DataPtr;
  

Не думаю, что это можно сделать, я перепробовал все мыслимые способы.

Этот код работает, как и в запущенной программе, я просто не могу освободить память. Каждый раз, когда вызывается этот код (включается не весь код, поскольку он не имеет значения), объем памяти увеличивается. Я думаю, что удаление происходит неправильно и что void * продолжает расти.

Я также изменил часть приведенного выше кода, основываясь на приведенных здесь рекомендациях, но при таком коде объем памяти продолжает расти.

Комментарии:

1. ColLenArray = new long(NumCols * sizeof(long)); это опечатка? Вы делаете ColLenArray[NumCols - 1] позже.

2. @Luc Я не вижу проблемы? ColLenArray — это указатель.

3. Указатель да, но на один длинный. Вы можете индексировать только указатель на элемент массива.

4. @Luc Я также вызываю этот код после создания указателя. SQLColAttribute(hstmt, ((SQLUSMALLINT) i) 1, SQL_DESC_OCTET_LENGTH, NULL, 0, NULL, amp;ColLenArray[i]); ColLenArray[i] = ALIGNBUF(ColLenArray[i]);

5.@PoiXen amp;ColLenArray[i] — это rvalue, с помощью которого вы не можете изменять, ColLenArray и ColLenArray[i] = ALIGNBUF(...); присваивание по-прежнему не изменяет ColLenArray и индексирует через него. Независимо от того, каким способом вы его нарезаете, вы каждый раз индексируете указатель на один long, поэтому я надеюсь i , что (и другие смещения) всегда равны 0… Это также относится к OffsetArray .

Ответ №1:

Вы не можете вызвать delete на void * .

Решение состоит в том, чтобы не приводить указатель на void** (который new void*[...] вам даст) к void* . Я действительно не знаю, что должен делать ваш код, но вы пробовали изменить тип DataPtr на void ** ?

В более общем плане, избегайте void* , насколько это возможно, C . Есть решения получше. Если вы отредактируете свой вопрос, чтобы описать, чего вы пытаетесь достичь, тогда мы, возможно, сможем что-то предложить.

Комментарии:

1. @user: Вы должны иметь возможность вызывать delete (или delete [] в данном случае) на void ** .

2. @Oli: Разумная формулировка «Избегать void»: D 1

Ответ №2:

Вы должны стараться избегать смешивания void* и new . На самом деле в C new предназначен для автоматического определения типа указателя; тогда почему бы его не использовать. По крайней мере, вы можете использовать char* , если вы просто имеете дело с необработанными байтами.

Другой момент — это new void*[SIZE] выделение void** . Итак, вам следует изменить объявление на void **DataPtr . Удалите приведение типов перед new . Теперь вы можете delete[] DataPtr; .

Редактировать:

В коде есть некоторые проблемы, переменные должны быть объявлены, как показано ниже:

 ColLenArray = new long[NumCols * sizeof(long)]; // declare as long[] (not long())
OffsetArray = new long[NumCols * sizeof(long)];
  

когда вы объявляете эти переменные как, new long() ; он просто инициализирует значение и присваивает указатель на single long .

Повреждение памяти происходит из-за того, что вы используете ColLenArray[i] , который обращается к неверной памяти. Поскольку вы собираетесь использовать вышеуказанные переменные в качестве массивов, это должно быть new long[] . Тогда повреждения памяти не произойдет. После использования вы должны delete[] их.

Комментарии:

1. @iammilind изменяет void DataPtr = (void )на новый void**[OffsetArray[numCols — 1] ColLenArray[numCols — 1] ALIGNBUF(sizeof(SQLINTEGER))]; на void ** DataPtr = новый void *[OffsetArray[numCols — 1] ColLenArray[numCols — 1] ALIGNBUF(sizeof(SQLINTEGER))]; похоже, память не освобождается, проверено в диспетчере задач, и memoery продолжает обновляться при каждом вызове функции.

2. Я предложил void** DataPtr = new void*[...]; в своем ответе. Вы пробовали это? Также при освобождении должно быть delete[] DataPtr; , поскольку вы выделяете массив.

Ответ №3:

Вам просто нужен блок памяти, который вы можете передать некоторым процедурам библиотеки базы данных? Распределить таким образом:

 char * buffer = new char[ len ];
  

len — это длина буфера в байтах. Чтобы удалить, просто выполните:

 delete [] buffer;
  

Вы хотите, чтобы void * передавался в функцию?

 void * DataPtr = static_cast< void* >( buffer );
  

Для получения дополнительных баллов за заслуги используйте boost для управления удалением:

 boost::scoped_array< char > buffer( new char[ len ] );
  

… тогда вам не нужно беспокоиться об удалении. Чтобы получить буфер здесь, вам нужно:

 void * DataPtr = static_cast< void* >( buffer.get() );