С++. Удаление двумерных динамических массивов

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

#include <iostream>

using namespace std;

inline void del_ptr_array(char** arr, unsigned int size) // здесь ошибка
// удаляет элементы массива указателей char**
{
    for (unsigned int i = 0; i < size; i++)
        delete[] arr[i];
    delete[] arr;
}

int main()
{
    unsigned int size = 1;
    char** words = new char* [size];
    words[0] = (char*)"words";

    del_ptr_array(words, size);

    return 0;
}

Функция del_ptr_array должна удалять двумерные массивы типа char**, это мне нужно для проекта. Но при вызове функции постоянно возникает исключение:

//
// delete_scalar.cpp
//
//      Copyright (c) Microsoft Corporation. All rights reserved.
//
// Defines the scalar operator delete.
//
#include <crtdbg.h>
#include <malloc.h>
#include <vcruntime_new.h>
#include <vcstartup_internal.h>

////////////////////////////////////////////////////////////////
// delete() Fallback Ordering
//
// +-------------+
// |delete_scalar<----+-----------------------+
// +--^----------+    |                       |
//    |               |                       |
// +--+---------+  +--+---------------+  +----+----------------+
// |delete_array|  |delete_scalar_size|  |delete_scalar_nothrow|
// +--^----^----+  +------------------+  +---------------------+
//    |    |
//    |    +-------------------+
//    |                        |
// +--+--------------+  +------+-------------+
// |delete_array_size|  |delete_array_nothrow|
// +-----------------+  +--------------------+

_CRT_SECURITYCRITICAL_ATTRIBUTE
void __CRTDECL operator delete(void* const block) noexcept
{
    #ifdef _DEBUG
    _free_dbg(block, _UNKNOWN_BLOCK); // здесь вызывается точка останова
    #else
    free(block);
    #endif
}

Чем может быть вызвано исключение? Как заставить это все работать? )) Буду благодарен за помощь.


Ответы (1 шт):

Автор решения: Harry

Смотрите, вот здесь вы выделяете память для words.

char** words = new char* [size];

Все нормально, и delete[] words оправданно и полно смысла — освободить и вернуть в пул памяти то, что было выделено.

Далее вы делаете

words[0] = (char*)"words";

Т.е. ваш words[0] указывает на память, которая через new НЕ выделалась. Так что удаление такой памяти в

for (unsigned int i = 0; i < size; i++)
    delete[] arr[i];

приводит к неопределенному поведению (читай — проблемам). Что не менее неприятно, все прочие words[i] никак не инициализировались вообще, и указывают на какие-то случайные места в памяти. Но эти случайные места вы тоже пытаетесь освободить! Итог — у вас сразу size проблем...

Удалять через delete можно только то, что выделялось через new!

Что делать? Зависит от того, что вы делаете.

Если вы используете указатели на строковые литералы или на иные, не выделенные через new области памяти — просто не освобождайте их.

Если хотите хранить в них что-то с выделением памяти и последующим освобождением — вы должны выделить им память (или хотя бы обнулить эти указатели).

→ Ссылка