那说的问题是:摆脱这种情况的最佳方法是什么:
最小的工作示例:
文件“myclass.h”:
#ifndef MYCLASS_H
#define MYCLASS_H
#include<vector>
using namespace std;
class myclass{
vector<int> *onTheHeap;
public:
myclass(int len=0){
onTheHeap = new vector<int>(len);
}
~myclass(){
delete onTheHeap;
}
};
#endif
file“static_loader.cpp”
#include "class.h"
myclass existsForever;
int cause_static_global_creation(){
existsForever = myclass(5);
}
static int bootstrap = cause_static_global_creation();
和文件“main.cpp”:
#include "class.h"
extern myclass existsForever;
int main(){
return 0;
}
构建:
g++ -g -c static_loader.cpp
g++ -g main.cpp static_loader.o
并以:
运行 valgrind --leak-check=full ./a.out
结果:当变量在main函数下面的exit处理程序中被调用时,该变量被释放,但是static_loader下面的main_initialization_and_destruction_0函数中的也是!
有没有办法确保这些变量一旦完全被释放,而不涉及广泛地重新分解代码?在我必须使用的库中,有几十个这种模式的实例......
编辑:
添加功能:
void operator=(myclass other){
delete this->onTheHeap;
this->onTheHeap = other.onTheHeap;
}
和
myclass(const myclass& other){
this->onTheHeap = new vector<int>(*(other.onTheHeap));
}
不会改变行为。
第二次编辑:
myclass& operator=(const myclass& other){
delete this->onTheHeap;
this->onTheHeap = new vector<int>(*(other.onTheHeap));
return *this;
}
解决所有问题。我的库有内存泄漏,无论如何都有这样的来源,但我不再确定如何重现它。至少它不是这个,并且感谢关于重构等的建议!
答案 0 :(得分:2)
你的假设被打破了。 myclass existsForever;
初始化不是cause_static_global_creation
,而是myclass::myclass
。相反,cause_static_global_creation
会为已初始化的对象分配值。
当班级违反三级规则时,任务会导致问题就不足为奇了。
答案 1 :(得分:1)
myclass
在您的示例中构造了两次。
首先,使用len=0
语句myclass existsForever;
。
稍后,在cause_static_global_creation
中使用len=5
构建临时实例,并使用默认赋值运算符将其分配给existsForever
。此时,existsForever
和临时将共享onTheHeap
指针的相同值。临时在cause_static_global_creation
中被立即销毁,释放了向量的内存。当全局实例被销毁时,程序端会再次释放相同的内存。
我有一些建议如何快速解决。
1.定义构造函数如下
myclass(int len=0)
{
if ( len > 0 )
onTheHeap = new vector<int>(len);
else
onTheHeap = NULL;
}
2.使用智能指针而不是裸指针。
std::shared_ptr<vector <int>> onTheHeap;
3.不要在堆上构造向量,而是使用实例成员。
更长的方法是正确实现赋值运算符和复制构造函数。
答案 2 :(得分:1)
我认为这些评论/策略涵盖了您的情况:
vector<int>*
替换为vector
即可。编译器将负责堆栈内存管理,您将避免堆泄漏。