Нужно ли освобождать память wchar, выделенную при использовании 'new', или delete [] также освобождает ее? - PullRequest
0 голосов
/ 03 июля 2019

Пытаюсь найти правильный способ освободить память, и я не могу найти однозначного ответа. Я уверен, что это там, но я не могу найти это, и я немного смущен.

Вот что я делаю. Я создаю новый sStructUsers из sUsers, затем я выделяю память для имени пользователя

    struct sStructUsers 
        {
        TCHAR *sName;
        };

    sStructUsers *sUsers = new sStructUsers[TOTALUSERS]();

    // Allocate memory for the TCHARs in sStruct
    for (INT k = 0; k < TOTALUSERS; k++)
        {
        sUsers [k].sName =  (TCHAR*)calloc(128,sizeof(TCHAR))
        }

Далее я делаю любую работу, которую мне нужно сделать с членом sName

    // do work here

Теперь, чтобы очистить, я делаю это:

    delete[] sUsers;

или мне это сделать?

    for (INT k = 0; k < TOTALUSERS; k++)
        {
        free(sUsers[k].sName);
        }
    delete[] sUsers?

Я не уверен, нужно ли мне освобождать память или если об этом позаботится delete []?

Ответы [ 3 ]

5 голосов
/ 03 июля 2019

Никогда не используйте new, если можете помочь.В современном C ++ в большинстве случаев new не требуется.Вы можете использовать std::vector, std::array, std::string (std::basic_string<TCHAR> возможно), std::unique_ptr или std::shared_ptr.

Если вы чувствуете, что вам действительно нужно использовать new, сделайте специальныйкласс, который справится с этим.То есть, например, сделать new в конструкторе и delete в деструкторе.

И, конечно, как было сказано в комментариях, никогда не путайте new / delete с malloc / free.Нет необходимости использовать эти функции в C ++ вообще, так как это остатки C.

Редактировать: Добавлен пример, как это может быть обработано самим классом.

struct sStructUsers 
{
    const int MAX_NAME_SIZE = 128;
    sStructUsers()
    {
        sName = new TCHAR[MAX_NAME_SIZE];
    }
    ~sStructUsers()
    {
        delete sName;
    }
    TCHAR *sName;
};

Тогдавам не нужна никакая инициализация / очистка при использовании этого класса.

Обратите внимание, что вам обычно не нужно даже этого делать, вы можете определить свой класс следующим образом:

struct sStructUsers 
{
    std::basic_string<TCHAR> sName;
};

И иметь полную string функциональность бесплатно.Или вот так, если вам действительно нужен указатель:

struct sStructUsers 
{
    const int MAX_NAME_SIZE = 128;
    sStructUsers() : sName(new TCHAR[MAX_NAME_SIZE]) {}
    std::unique_ptr<TCHAR[]> sName;
};

Или, как я упоминал ранее, используйте другие стандартные контейнеры.

1 голос
/ 03 июля 2019

Комментарии и ответы, которые рекомендуют более предпочтительные контейнеры, более идиоматический C ++ и более современные практики, все в порядке.

Но на ваш ближайший вопрос отвечает ваш второй вариант

for (INT k = 0; k < TOTALUSERS; k++)
    {
    free(sUsers[k].sName);
    }
delete[] sUsers;

Это не приведет к утечке памяти.Однако ваш первый вариант будет пропущен, потому что простое delete[] массива не освободит кучу памяти его элементов.

Короче говоря, используйте delete[] для каждого new[] и free для каждого calloc.

(Только тогда возможно рефакторинг будет ближе к C ++, чем смесь Cи C ++)

1 голос
/ 03 июля 2019

Каждое распределение должно быть освобождено. По какому-то коду. Как писал sklott , есть инструменты (контейнеры и другие классы), которые делают эту работу за вас. Если какой-то другой код этого не делает, то ваш код должен выполнить освобождение.

Короче, вы должны позвонить как free(sUsers[k].sName), так и delete[] sUsers. Как бы то ни было, удаление [] sStructUsers s не освободит указатели внутри него.

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

(Ответчикам и комментаторам, которые разместили сообщение «Никогда не путайте новое / удаляйте с malloc / free», пожалуйста, напишите мне, объяснив, почему. Всегда важно понимать рациональные советы и лучшие практики. Обновление : очевидно, что вы не должны смешивать new + free или malloc + delete и т. Д .; такие функции должны быть правильно спарены, чтобы не допустить повреждения кучи и утечек. Более тонкий вопрос - почему бы не использовать new + delete для некоторых выделений и malloc / calloc + бесплатно для других [еще лучше: CoTaskMemAlloc (), HeapAlloc (), VirtualAlloc () или другие функции платформ ...].)

...