如何停止内存泄漏
How do I stop memory Leaks?
我不断收到来自编译器的错误消息,说存在内存泄漏,两个 8 字节块和一个 5 字节块。我已经删除了析构函数中的*name
数组。析构函数如何处理范围?我的印象是,一旦主对象结束,fruit
对象将被删除,因为它们超出了范围。
#include "Fruit.h"
#include "LeakWatcher.h"
using namespace std;
Fruit::Fruit(const Fruit &temp )
{
name = temp.name;
for(int i = 0; i < CODE_LEN - 1; i++)
{
code[i] = temp.code[i];
}
}
void Fruit::operator=(const Fruit &tempFruit)
{
name = tempFruit.name;
for(int i = 0; i < CODE_LEN; i++)
{
code[i] = tempFruit.code[i];
}
}
Fruit::~Fruit()
{
delete[] name;
}
bool Fruit::operator==(const Fruit &tempFruit)
{
int i = 0;
while(name[i] != NULL && tempFruit.name[i] != NULL)
{
if(name[i] != tempFruit.name[i])
return false;
i++;
}
if(name[i] != NULL || tempFruit.name[i] != NULL)
return false;
return true;
}
bool Fruit::operator<(const Fruit &tempFruit)
{
int i = 0;
while(name[i] != NULL && tempFruit.name[i] != NULL)
{
if((int)name[i] < (int)tempFruit.name[i])
return true;
else if((int)name[i] > (int)tempFruit.name[i])
return false;
i++;
}
if(name[i] == NULL && tempFruit.name[i] != NULL)
return true;
else
return false;
}
std::ostream & operator<<(std::ostream &os, const Fruit *printFruit)
{
os << setiosflags(ios::left) << setw(MAX_NAME_LEN) << printFruit->name << " ";
for(int i = 0; i < CODE_LEN; i++)
{
os << printFruit->code[i];
}
os << endl;
return os;
}
std::istream & operator>>(std::istream &is, Fruit *readFruit)
{
string tempString;
is >> tempString;
int size = tempString.length();
readFruit->name = new char[tempString.length()];
for(int i = 0; i <= (int)tempString.length(); i++)
{
readFruit->name[i] = tempString[i];
}
readFruit->name[(int)tempString.length()] = ' ';
for(int i =0; i < CODE_LEN; i++)
{
is >> readFruit->code[i];
}
return is;
}
void stuff()
{
}
void main()
{
_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
Fruit *fruit = new Fruit();
Fruit *fruit1 = new Fruit();
cin >> fruit;
*fruit1 = *fruit;
cout << fruit << fruit1;
_CrtDumpMemoryLeaks();
}
H
#ifndef _FRUIT_H
#define _FRUIT_H
#include <cstring>
#include <sstream>
#include <iomanip>
#include <iostream>
enum { CODE_LEN = 4 };
enum { MAX_NAME_LEN = 30 };
class Fruit
{
private:
char *name;
char code[CODE_LEN];
public:
Fruit(const Fruit &temp);
Fruit(){name = NULL;};
bool operator<(const Fruit &other);
friend std::ostream & operator<<(std::ostream &os, const Fruit *printFruit);
bool operator==(const Fruit &other);
bool operator!=(const Fruit &other){return!(*this==other);};
friend std::istream & operator>>(std::istream& is, Fruit *readFruit);
void Fruit::operator=(const Fruit &tempFruit);
~Fruit();
};
#endif
看来"泄漏"的主要来源是"水果"和"水果1"指针 - _CrtDumpMemoryLeaks(( 检查尚未释放的内存。在调用它之前,您需要删除这两个指向的数据。
也就是说,您还有其他问题。
C++没有自动垃圾回收功能。您必须跟踪和管理内存分配,或者使用为您执行此操作的类/代码。
请考虑以下代码:
void iNeedALeak() {
void* p = new char[64];
strcpy(p, "Hello world");
std::cout << p << std::endl;
}
此代码进行了分配,并将其存储在"p"中。尽管我们将该值用于几个函数,但我们从未存储过它。因此,它永远不会返回到系统中。
代码中等待发生的泄漏的一个示例是在运算符中>>
std::istream & operator>>(std::istream &is, Fruit *readFruit)
{
string tempString;
is >> tempString;
int size = tempString.length();
readFruit->name = new char[tempString.length()];
是的,在您的删除运算符中,您可以从名称中删除 []。但这只能处理您的代码到达 ~Fruit 的情况,请考虑:
Fruit f;
cin >> f; // readFruit->name = new char[]..
cin >> f; // readFruit->name = new char[]...
此时,您不再存储原始值,并且您没有删除它。
实际上,您遇到的问题是您使用的是非常类似于C的方法。如果你打算用C++编写这个,你应该考虑使用 RAII,例如你可以使用 std::unique_ptr 类。
TL;DR 不要公开原始指针,将它们封装在确保它们超出范围或重新分配到时被释放的东西后面。
当您的水果对象超出范围时,不会删除它们。相反,它们会泄漏。由于这是程序执行的最后一件事,因此没有真正的后果,一旦程序退出,操作系统将回收内存。尽管如此,这是一个泄漏。
为什么不直接在堆栈上创建它们呢?
与其解决您的示例中的特定内存问题,我已经在注释中这样做了,我会通过使用 std::string
和 std::array
来完全避免它们。您的代码将归结为
#include <iostream>
#include <string>
#include <array>
enum { CODE_LEN = 4 };
class Fruit
{
private:
std::string name;
std::array<char,CODE_LEN> code;
public:
bool operator<(const Fruit &other);
bool operator==(const Fruit& other);
bool operator!=(const Fruit& other) {return!(*this==other);}
friend std::ostream& operator<<(std::ostream &os, const Fruit& f);
friend std::istream& operator>>(std::istream& is, Fruit& f);
};
请注意,没有用户定义的构造函数、赋值运算符或析构函数。一些运算符也可以大大简化,例如
bool Fruit::operator==(const Fruit& rhs)
{
return code == rhs.code;
}
bool Fruit::operator<(const Fruit& rhs)
{
return name < rhs.name;
}
- C++功能泄漏内存,我是C++新手,不确定如何解决
- 我的堆栈弹出式磁带的实现是否泄漏内存?
- 将 c++ 向量转换为字符 ** 而不会泄漏内存
- 析构函数 C++ 使泄漏内存
- 构造函数对象赋值是否泄漏内存
- corba :: orb_init泄漏内存
- Gmock泄漏内存
- 如何在不泄漏内存的情况下删除链接列表
- Visual C ODBC关闭记录集泄漏内存
- 为什么泄漏内存比在动态数组上执行 delete[] 慢
- OpenGL正在泄漏内存.哪个对象未释放
- 可以std ::退出泄漏内存
- uiautomation findall泄漏内存
- 为什么在此OpenCL代码中泄漏内存,为什么要泄漏内存
- pthread在完成后会泄漏内存
- win32 标准::线程泄漏内存
- 返回指向同一变量的指针是否会泄漏内存
- 使用clectType(new any_type())可能会泄漏内存泄漏
- Windows开发:如何确定我的应用程序是否正在泄漏内存
- WinHttp打开泄漏内存