复制构造函数中的内存泄漏
Memory leaks in copy constructor
我看了很多关于copy constructor内存泄露的解决方法,但是还是没明白怎么解决。
例如,我有一个 "Person" class 具有这些成员和函数(头文件):
#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();
};
在这个程序中,我试图将 "Objects" 输入到 Vector,而 Person 和 Vector 继承自 Object。
在两个复制常量中,我都有内存泄漏问题(程序运行良好)。
例如,在这段代码中,我得到了所有这 5 个字符数组的内存泄漏。我在 Vector 内存泄漏方面也有更多问题,但让我们从 main 中的这个简单代码开始(char 数组发生 5 次内存泄漏):
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;
}
人 class 是:
#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;
}
非常感谢您的帮助!!
您不仅仅是内存泄漏。您有一个 full-fledged、memory-corrupting、未定义的行为:
Person::Person(char * name)
{
delete this->p_name;
这是您的构造函数。 p_name
class 成员似乎没有以任何方式初始化。你做的第一件事就是尝试 delete
它。
因此,无论随机值 p_name
将包含什么,由于最近的一组宇宙射线撞击保持其初始值的 RAM 电容器,构造函数做的第一件事就是尝试释放pointed-to内存。
在您担心复制构造函数的任何所谓泄漏之前,您需要在其他地方解决一堆问题,例如这个问题。
删除有一些问题。
在你的 main 中,在第一个 while 你必须删除 temp
;在第二口井中不要使用它,使用 delete [] persons
.
在您的复制构造函数中不要使用 delete this->p_name
,那是不正确的。
首先你必须将指针设置为空,所以 p_name=NULL,然后使用 setter 和 getter,对你的值构造函数也是如此。
并且在你的析构函数中,在删除它之前测试 p_name 是否存在。
在 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);
}
在 main() 中,tmp 字符数组没有被删除,这是我看到的第一个内存泄漏。
在 Person(char * name) 构造函数中调用 delete on
Person::Person(char * name)
{
delete this->p_name;
p_name 未分配,因此行为未定义。而p_name是一个数组,所以应该使用delete[]。
如果使用std::stringclass,至少可以避免delete和delete[]
的混淆
我看了很多关于copy constructor内存泄露的解决方法,但是还是没明白怎么解决。
例如,我有一个 "Person" class 具有这些成员和函数(头文件):
#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();
};
在这个程序中,我试图将 "Objects" 输入到 Vector,而 Person 和 Vector 继承自 Object。 在两个复制常量中,我都有内存泄漏问题(程序运行良好)。
例如,在这段代码中,我得到了所有这 5 个字符数组的内存泄漏。我在 Vector 内存泄漏方面也有更多问题,但让我们从 main 中的这个简单代码开始(char 数组发生 5 次内存泄漏):
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;
}
人 class 是:
#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;
}
非常感谢您的帮助!!
您不仅仅是内存泄漏。您有一个 full-fledged、memory-corrupting、未定义的行为:
Person::Person(char * name)
{
delete this->p_name;
这是您的构造函数。 p_name
class 成员似乎没有以任何方式初始化。你做的第一件事就是尝试 delete
它。
因此,无论随机值 p_name
将包含什么,由于最近的一组宇宙射线撞击保持其初始值的 RAM 电容器,构造函数做的第一件事就是尝试释放pointed-to内存。
在您担心复制构造函数的任何所谓泄漏之前,您需要在其他地方解决一堆问题,例如这个问题。
删除有一些问题。
在你的 main 中,在第一个 while 你必须删除 temp
;在第二口井中不要使用它,使用 delete [] persons
.
在您的复制构造函数中不要使用 delete this->p_name
,那是不正确的。
首先你必须将指针设置为空,所以 p_name=NULL,然后使用 setter 和 getter,对你的值构造函数也是如此。
并且在你的析构函数中,在删除它之前测试 p_name 是否存在。
在 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);
}
在 main() 中,tmp 字符数组没有被删除,这是我看到的第一个内存泄漏。
在 Person(char * name) 构造函数中调用 delete on
Person::Person(char * name)
{
delete this->p_name;
p_name 未分配,因此行为未定义。而p_name是一个数组,所以应该使用delete[]。
如果使用std::stringclass,至少可以避免delete和delete[]
的混淆