Как правильно удалить эти указатели? - PullRequest
0 голосов
/ 10 октября 2018

Это мое распределение:

for (int i = 0; i < numCols; i++)
{
    columnNameLen = new SQLSMALLINT *[numCols];
    columnDataType = new SQLSMALLINT *[numCols];
    columnDataSize = new SQLULEN *[numCols];
    columnDataDigits = new SQLSMALLINT *[numCols];
    columnDataNullable = new SQLSMALLINT *[numCols];
    columnData = new SQLWCHAR *[numCols];
    columnDataLen = new SQLLEN *[numCols];
    columnName = new SQLWCHAR *[numCols];
}

for (int i = 0; i < numCols; i++)
{
    columnNameLen[i] = new SQLSMALLINT;
    columnDataType[i] = new SQLSMALLINT;
    columnDataSize[i] = new SQLULEN;
    columnDataDigits[i] = new SQLSMALLINT;
    columnDataNullable[i] = new SQLSMALLINT;
    columnDataLen[i] = new SQLLEN;
    columnName[i] = new SQLWCHAR[256];
}

И это мое удаление:

for (int i = 0; i < numCols; i++)
{
    delete columnNameLen[i];
    columnNameLen[i] = NULL;
    delete columnDataType[i];
    columnDataType[i] = NULL;
    delete columnDataSize[i];
    columnDataSize[i] = NULL;
    delete columnDataDigits[i];
    columnDataDigits[i] = NULL;
    delete columnDataNullable[i];
    columnDataNullable[i] = NULL;
    delete columnData[i];
    columnData[i] = NULL;
    delete columnDataLen[i];
    columnDataLen[i] = NULL;
    delete[] columnName[i];
    columnName[i] = NULL;
}

for (int i = 0; i < numCols; i++)
{
    delete[] columnNameLen;
    columnNameLen = NULL;
    delete[] columnDataType;
    columnDataType = NULL;
    delete[] columnDataSize;
    columnDataSize = NULL;
    delete[] columnDataDigits;
    columnDataDigits = NULL;
    delete[] columnDataNullable;
    columnDataNullable = NULL;
    delete[] columnData;
    columnData = NULL;
    delete[] columnDataLen;
    columnDataLen = NULL;
    delete[] columnName;
    columnName = NULL;
}

Код выше?Я, вероятно, должен просто использовать умные указатели, но я не знаю, как будет выглядеть код с ними?Так что, если вы добавите код смарт-указателя, это будет с благодарностью.Эти указатели используются локально в функции потока и ни с кем не делятся.

Боюсь, что для второго цикла нужно всего лишь delete, а не delete[].

TIA!

Ответы [ 4 ]

0 голосов
/ 10 октября 2018

Если вы не можете отказаться от указателей (иногда нет другого пути) и не хотите использовать ни одну из предложенных альтернатив, рассмотрите возможность использования SCOPE_EXIT аналога, например Boost.ScopeExit.Затем вы можете сделать что-то вроде:

SCOPE_EXIT(p, delete p);
0 голосов
/ 10 октября 2018

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

Для освобождения второй цикл не нужен.Это позволит избежать того, что вы удаляете первый раз, когда указатель и следующие итерации пытаются удалить nullptr.

Кстати:

  • используйте nullptr вместо NULL
  • , вы также можете использовать shared_ptr или unique_ptr в зависимости от необработанного указателя.
  • используйте векторы вместо массивов, если это возможно.
0 голосов
/ 10 октября 2018

Вы не должны использовать указатели вообще здесь.

using SQLSTRING = std::basic_string<SQLWCHAR>;

struct Column
{
    SQLSTRING Name;
    SQLSTRING Data;
    SQLSMALLINT DataType;
    SQLULEN DataSize;
    SQLSMALLINT DataDigits;
    SQLSMALLINT DataNullable;
}

std::vector<Column> columns(numCols);
0 голосов
/ 10 октября 2018

Не используйте new и delete в коде пользователя.Используйте std::vector<>.

Относительно new и delete:

Все объекты, выделенные с new, должны быть освобождены на delete,все объекты, выделенные с помощью new[], должны быть освобождены с помощью delete[].

Также убедитесь, что вы следуете правилу 3/5 .(Правило 0 ..., к которому вы должны стремиться ... не подлежит сомнению, если вы не используете умные указатели или другие объекты, которые следуют за RAII / RDID, чтобы обернуть необработанные указатели владения).

...