如何删除使用 _strdup() 创建的 const char*

How to delete a const char* created with _strdup()

我在 Visual Studio 中使用以下代码来存储构造函数参数 char* 并在我的 class.

的解构中删除它
#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,就会造成内存泄漏。如果我使用它,我会在调试时遇到这个未知错误。

正确的做法是什么?


delete[]更改为free后:

有许多不同的分配方案。太多了,无法猜测或假设如何释放东西。因此,您首先要查找有关该功能的文档。即使只是谷歌搜索 "msdn _strdup" 之类的东西也经常到达那里或关闭(对于 Windows / Visual Studio / Microsoft 附带的东西)。

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

The _strdup function calls malloc to allocate storage space for a copy of strSource and then copies strSource to the allocated space.

Because _strdup calls malloc to allocate storage space for the copy of strSource, it is good practice always to release this memory by calling the free routine on the pointer that's returned by the call to _strdup.

所以你需要使用free

这里有几个问题。

  1. delete[]而不是free

    strdup 来自 C 库。 The documentation 告诉我们如何清理它。

    微软的类似 _strdup works the same way.

    您必须阅读所用函数的文档,尤其是当您在使用这些函数时遇到问题时。这就是它存在的原因。

  2. 您手动调用了 A 的析构函数,而您不应该这样做。

    对象有自动保存期限,会自动销毁。当您出于某种原因自己调用析构函数时,这意味着它最终将被调用 两次。这意味着错误的释放调用 delete[] myChar 也将被调用两次,这显然是错误的。

  3. 您的对象的复制语义已损坏。

    好的,所以你不要在这里复制它。但是任何管理内存的对象都应该遵循零规则、三规则或五规则。

  4. 你太早检查泄漏了。

    myA在调用_CrtDumpMemoryLeaks()的时候还活着,当然会看到还没有destroyed/freed,就认为是内存泄漏.您应该在尝试摆脱所有资源之后调用该函数,而不是之前。

这是您的直接固定代码:

#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
}