Как удалить const char *, созданный с помощью _strdup () - PullRequest
0 голосов
/ 03 марта 2020

Я использую следующий фрагмент кода в Visual Studio для хранения параметра конструктора char * и удаления его в деконструкции моего класса.

#include "pch.h"
#include <iostream>

class A
{
public:
    A(const char *fn) {
        myChar = _strdup(fn);
    }

    ~A() {
        delete[] myChar;
    }

    char *myChar;
};


int main()
{
    A myA("lala");
    myA.~A();

    _CrtDumpMemoryLeaks(); //leak detector
}

Если я не использую delete [] myChar Я создаю утечку памяти. Если я использую его, я получаю эту неизвестную ошибку при отладке.

enter image description here

Какой правильный способ сделать это?


После изменения delete[] на free:

https://i.stack.imgur.com/VIbNo.png

Ответы [ 2 ]

6 голосов
/ 03 марта 2020

Здесь есть несколько проблем.

  1. Вы delete[] вместо free.

    strdup происходит от C библиотека. Документация говорит нам, как ее очистить.

    Аналог Microsoft _strdup работает так же .

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

  2. Вы вызываете деструктор A вручную, когда не должны.

    Объект имеет automati c срок хранения, и будет уничтожен автоматически. Когда вы по какой-то причине сами вызываете деструктор, это означает, что в конечном итоге он будет называться дважды . Это означает, что ошибочный вызов освобождения delete[] myChar также будет вызываться дважды, что явно является проблемой.

  3. Семантика копирования вашего объекта нарушена.

    Хорошо, так что не копируйте это здесь. Но любой объект, который управляет памятью, должен следовать правилу нуля, правилу трех или правилу пяти.

  4. Вы проверяете утечки слишком рано.

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

Вот ваш непосредственно исправленный код:

#include "pch.h"
#include <iostream>

class A
{
public:
    A(const char *fn) {
        myChar = _strdup(fn);
    }

    A(const A& other) {
        myChar = _strdup(other.myChar);
    }

    A& operator=(const A& other) {
        if (&other != this) {
           free(myChar);
           myChar = _strdup(other.myChar);
        }

        return *this;
    }

    ~A() {
       free(myChar);
    }

    char *myChar;
};


int main()
{
    {
       A myA("lala");
    }

    _CrtDumpMemoryLeaks(); //leak detector
}

И вот что должно было быть:

#include <string>
#include <utility>   // for std::move
#include <crtdbg.h>  // for _CrtDumpMemoryLeaks

class A
{
public:
    A(std::string str) : m_str(std::move(str)) {}

private:
    std::string str;
};

int main()
{
   {
      A myA("lala");
   }

   _CrtDumpMemoryLeaks(); // leak detector
}
0 голосов
/ 03 марта 2020

Существует много различных схем распределения. Слишком много, чтобы просто угадать или предположить, как освободить вещи. Итак, вы сначала посмотрите документацию по функции. Даже просто прибегая к помощи чего-то вроде «msdn _strdup», он часто оказывается там или близко (для вещей, которые поставляются с Windows / Visual Studio / Microsoft).

https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strdup-wcsdup-mbsdup?view=vs-2019

Функция _strdup вызывает mallo c для выделения пространства для хранения копии strSource, а затем копирует strSource в выделенное пространство.

и

Потому что _strdup вызывает mallo c для выделения пространства для хранения копии strSource. Рекомендуется всегда освобождать эту память, вызывая свободную процедуру для указателя, возвращаемого при вызове _strdup.

Так что вам нужно использовать free

...