A Simple String Class
#pragma once
#include <iostream>
#include <cstring>
class MyString
{
private:
int buf_len;
char *characters;
public:
MyString(int buf_len = 64, const char *data = NULL)
{
std::cout << "Constructor(int, char*)" << std::endl;
this->buf_len = 0;
this->characters = NULL;
create(buf_len, data);
}
~MyString()
{
delete[] this->characters;
}
bool create(int buf_len, const char *data)
{
this->buf_len = buf_len;
if (this->buf_len != 0)
{
this->characters = new char[this->buf_len]{};
if (data)
strncpy(this->characters, data, this->buf_len);
}
return true;
}
friend std::ostream &operator<<(std::ostream &os, const MyString &ms)
{
os << "buf_len = " << ms.buf_len;
os << ", characters = " << static_cast<void *>(ms.characters);
os << " [" << ms.characters << "]";
return os;
}
};
采用动态内存,再构造函数中申请内存,再析构函数中释放内存,是不是就万事大吉呢?我们运行一下程序
#include <iostream>
#include "mystring.hpp"
using namespace std;
// Why memory leak and memory double free?
int main()
{
MyString str1(10, "Shenzhen");
cout << "str1: " << str1 << endl;
MyString str2 = str1; // 调用了copy constructor,str1和str2 指向的相同的内存空间
cout << "str2: " << str2 << endl;
MyString str3; // 调用了默认的构造函数,
cout << "str3: " << str3 << endl;
str3 = str1; // 这时赋值操作,编译器会生成=的运算符重载,把str1的成员拷贝给str2
cout << "str3:" << str3 << endl;
return 0;
}
这时这三个对象指向的内存空间相同,再程序即将完成退出之前,要执行析构函数对他们的内存销毁,执行完一个对象内存销毁之后,再进行第一个对象内存销毁时,就会出错。再
str3
创建的时候,会开辟一块内存空间,但是当str3 = str1
之后,str3的变量characters修改了内存地址,所以没有变量指向这块内存地址,就会造成内存泄漏。
这种内存泄漏的bug非常难排查。那么应该如何避免呢?