【问题标题】:Memory leaks in copy constructor复制构造函数中的内存泄漏
【发布时间】:2016-01-13 12:39:25
【问题描述】:

我尝试阅读了很多关于复制构造函数中发生内存泄漏的解决方案,但我仍然不明白如何解决它。

例如,我有一个“Person”类,它具有这些功能和功能(头文件):

#include "Object.h"
#include <string.h>
#include <iostream>
using namespace std;
class Person: public Object
{

private:
    char * p_name;
    int  length;
public:
    virtual Object * copy() const;
    virtual void print(ostream & os) const;
    Person(char * name);
    Person(const Person & per);
    ~Person();
};

在这个程序中,我试图将“对象”输入到 Vector,而 Person 和 Vector 从 Object 继承。 在这两个副本中,我都有内存泄漏问题(程序运行良好)。

例如,在这段代码中,我得到了所有这 5 个字符数组的内存泄漏。我在 Vector 内存泄漏方面也有更多问题,但让我们从 main 中的这个简单代码开始(发生 5 次 char 数组的内存泄漏):

int main ()
{
    const int SIZE = 5;
    Person* persons[SIZE];
    int i;

    // preparation of name array 
    for (i = 0; i<SIZE; i++) {
        char* tmp = new char[10];
        sprintf(tmp, "P-%d", i);
        persons[i] = new Person(tmp);
    }

    for (i = 0; i < SIZE; i++)
        delete persons[i];

    return 0;
}

Person 类是:

#include "Person.h"
using namespace std;



Object * Person::copy() const
{
    Person * p = new Person(*this);
    return p;
}

void Person::print(ostream & os) const
{
    for (int i = 0; i < this->length-1; i++)
    {
        os << this->p_name[i];
    }
}


Person::Person(char * name)
{
    delete this->p_name;
    this->length = strlen(name)+1;
    p_name = new char[length];
    strncpy(p_name, name, length);
}

Person::Person(const Person & per)
{
    delete[] this->p_name;
    this->length = strlen(per.p_name) + 1;
    this->p_name = new char[this->length];
    strncpy(this->p_name, per.p_name, this->length);
}

Person::~Person()
{
    delete[] this->p_name;
}

感谢您的帮助!!

【问题讨论】:

  • 如果你切换到std::string,这会容易得多。
  • 首先,您并没有删除您在 main 中分配的 tmp 数组,因此这可能是您遇到的内存泄漏之一。
  • 你需要使你的析构函数虚拟(在你的Object类以及你的Person类中)。
  • @Rabbid76 没有帮助。它仍然是未定义的行为,因为 p_name 未初始化。
  • 如果手动管理内存这个很难,你应该坚持std::stringstd::make_unique等,永远不要再使用new

标签: c++ memory memory-management memory-leaks copy-constructor


【解决方案1】:

在 main() 中,tmp char 数组没有被删除,这是我看到的第一个内存泄漏。

在 Person(char * name) 构造函数中调用删除

Person::Person(char * name)
{
     delete this->p_name;

p_name 未分配,因此行为未定义。而p_name是一个数组,所以应该使用delete[]。

如果使用std::string类,至少可以避免delete和delete[]的混淆

【讨论】:

  • 谢谢,所以有办法通过程序删除它,或者我应该从主程序中删除它?
  • 每个new 必须有一个对应的delete。如果你在循环开始时调用new,你应该在循环结束时调用delete。注意:在这种情况下,delete[]
  • 是的。这是我老师派来的测试仪,所以我有点瞎,没看到。谢谢你的帮助!!我真的很喜欢它!
【解决方案2】:

您不仅仅是内存泄漏。你有一个成熟的、破坏内存的、未定义的行为:

Person::Person(char * name)
{
    delete this->p_name;

这是你的构造函数。 p_name 类成员似乎没有以任何方式初始化。你做的第一件事就是尝试delete它。

因此,无论p_name 包含什么随机值,由于最近一组宇宙射线撞击保持其初始值的 RAM 电容器,构造函数所做的第一件事就是尝试释放指向的内存.

在您担心复制构造函数有任何所谓的泄漏之前,您需要在其他地方解决一系列问题,例如这个。

【讨论】:

    【解决方案3】:

    在 main() 中,你准备 c 你分配 5 个字符缓冲区,这些缓冲区永远不会被释放

    也(不是说 std::string 可以帮助你处理你的字符串),去掉不需要的 "this->"s:

    Person::Person(const Person & per)  
    {
        delete[] this->p_name;
        this->length = strlen(per.p_name) + 1;
        this->p_name = new char[this->length];
        strncpy(this->p_name, per.p_name, this->length);
    }
    

    可能看起来像这样:

    Person::Person(const Person & per)
    {
        delete[] p_name;
        length = strlen(per.p_name) + 1;
        p_name = new char[length];
        strncpy(p_name, per.p_name, length);
    }
    

    【讨论】:

      【解决方案4】:

      删除有一些问题。

      在你的主目录中,首先你必须删除temp;在第二个井中不要使用它,使用delete [] persons

      在你的复制构造函数中不要使用delete this-&gt;p_name,这是不正确的。

      首先,您必须将指针设置为 null,因此 p_name=NULL,然后使用 setter 和 getter,对于您的值构造函数也是如此。

      在你的析构函数中,在删除它之前测试 p_name 是否存在。

      【讨论】:

      • delete[] persons 不起作用,因为 persons 没有分配给 new[]
      • 另外,删除前不需要检查 null:删除空指针是无操作的。
      • 你可以重载它,这样你就可以正确地销毁你的数组对象或者不使用它,使用你的析构函数。
      猜你喜欢
      • 2021-06-17
      • 1970-01-01
      • 1970-01-01
      • 2013-01-12
      • 1970-01-01
      • 1970-01-01
      • 2019-08-19
      • 1970-01-01
      • 2018-11-18
      相关资源
      最近更新 更多