【发布时间】:2016-05-03 16:05:33
【问题描述】:
所以我有一个看起来像这样的基类:
class base {
public:
base() {
std::cout << "We created a base!" << std::endl;
}
~base() {
std::cout << "We destroyed a base!" << std::endl;
}
};
我有一个如下所示的派生类:
class leaks_memory : public base {
public:
leaks_memory(size_t count) :
memory(new int[count]), size_of_memory(count)
{
announce();
}
leaks_memory(const leaks_memory & lm) :
leaks_memory(lm.size_of_memory)
{
std::copy(lm.memory, lm.memory + size_of_memory, memory);
}
void swap(leaks_memory & lm) noexcept {
std::swap(lm.memory, memory);
std::swap(lm.size_of_memory, size_of_memory);
}
leaks_memory(leaks_memory && lm) {
swap(lm);
}
leaks_memory & operator=(leaks_memory lm) {
swap(lm);
return *this;
}
~leaks_memory() {
delete[] memory;
dennounce();
}
int & operator[](size_t index) {
return memory[index];
}
const int & operator[](size_t index) const {
return memory[index];
}
private:
int * memory;
size_t size_of_memory;
void announce() const noexcept {
std::cout << "We created a Leaks Memory!" << std::endl;
}
void dennounce() const noexcept {
std::cout << "We destroyed a Leaks Memory!" << std::endl;
}
};
现在,这些都不是问题,直到我编写如下所示的代码:
int main() {
std::unique_ptr<base> base_ptr;
std::atomic_bool done = false;
std::thread input_thread{ [&done] {
std::getline(std::cin, std::string());
done = true;
} };
while (!done) {
base_ptr = std::make_unique<leaks_memory>(20'000);
}
input_thread.join();
return 0;
}
这段代码每次循环迭代都会泄漏 20kb,因为 leaks_memory 析构函数永远不会被调用!
现在,很明显,我可以通过编辑 base 来解决这个问题:
virtual ~base() {
std::cout << "We destroyed a base!" << std::endl;
}
确实,如果我在进行此更改后运行相同的代码,我将不再有这种内存泄漏。
但是,如果我无法编辑 base 类怎么办?有没有办法在不完全改变执行代码的设计的情况下防止内存泄漏?
【问题讨论】:
-
在基类中有一个
virtual析构函数。 -
@MichaelWalz:不一定,它确实会增加性能损失。任何可能被继承的类都应该是虚拟的。
-
@MichaelWalz 不一定,很多情况下我不需要虚拟析构函数,想避免生成vtable。
-
@Xirema 好吧,那么答案是:不,不改变基类是不可能的。
-
您的程序有未定义的行为,而不是内存泄漏。如果您使用带有智能指针的自定义删除器(可能必须使用 shared_ptr 或您自己品牌的 unique_ptr),则可以摆脱它。
标签: c++ inheritance memory-management memory-leaks virtual-functions