首页 > 解决方案 > 如何删除使用 _strdup() 创建的 const char*

问题描述

我在 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,我会造成内存泄漏。如果我使用它,我会在调试时收到这个未知错误。

在此处输入图像描述

这样做的正确方法是什么?


更改delete[]为后free

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

标签: c++memorymemory-leakschar

解决方案


这里有几个问题。

  1. delete[]代替free.

    strdup来自 C 库。文档告诉我们如何清理它。

    微软的类似_strdup 工作方式相同

    您必须阅读您使用的函数的文档,尤其是当您遇到问题时。这就是为什么它在那里。

  2. A你不应该手动调用析构函数。

    该对象具有自动存储期限,并将自动销毁。当你出于某种原因自己调用析构函数时,这意味着它最终会被调用两次。这意味着错误的释放调用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
}

推荐阅读