当前位置:网站首页>如果在构造函数中抛出异常,最好的做法是防止内存泄漏?
如果在构造函数中抛出异常,最好的做法是防止内存泄漏?
2022-07-07 21:58:00 【大桑树保安队】
如果在构造函数中抛出异常,析构函数将不会被调用(简单类,不继承).因此,如果在构造函数中抛出异常,并且有一些堆内存未被清除的机会.那么这里最好的做法是什么?
如果你避免“裸”资源(如裸指针,裸互斥体等),并将所有内容都包含在具有适当RAII行为的容器或类中,那么即使存在异常,也不会有您所描述的问题.
也就是说,不要在构造函数中获取裸资源.而是创建一个本身跟随RAII的对象的实例.这样,即使您的构造函数失败(即创建实例的构造函数),将调用初始化对象的析构函数.
所以,这是不好的做法:
#include<iostream>
#include<stdexcept>
struct Bad {
Bad() {
double *x = new double;
throw(std::runtime_error("the exception was thrown"));
}
~Bad() {
delete x;
std::cout<<"My destructor was called"<<std::endl;
}
double *x;
};
int main() {
try {
Bad bad;
} catch (const std::exception &e) {
std::cout<<"We have a leak! Let's keep going!"<<std::endl;
}
std::cout<<"Here I am... with a leak..."<<std::endl;
return 0;
}
输出:
We have a leak! Let's keep going!
Here I am... with a leak...
一个更正的例子:
#include<iostream>
#include<stdexcept>
struct Resource {
Resource() {
std::cout<<"Resource acquired"<<std::endl;
}
~Resource() {
std::cout<<"Resource cleaned up"<<std::endl;
}
};
struct Good {
Good() {
std::cout<<"Acquiring resource"<<std::endl;
Resource r;
throw(std::runtime_error("the exception was thrown"));
}
~Good() {
std::cout<<"My destructor was called"<<std::endl;
}
};
int main() {
try {
Good good;
} catch (const std::exception &e) {
std::cout<<"We DO NOT have a leak! Let's keep going!"<<std::endl;
}
std::cout<<"Here I am... without a leak..."<<std::endl;
return 0;
}
输出:
Acquiring resource
Resource acquired
Resource cleaned up
We DO NOT have a leak! Let's keep going!
Here I am... without a leak...
我的观点如下:尝试将需要解放的所有资源封装到构造函数不抛出的类中,析构函数正确地释放资源.然后,在析构函数可能抛出的其他类中,只需创建包装资源的实例,并将保证获取的资源包装器的析构函数将被清理.
以下可能是一个更好的例子:
#include<mutex>
#include<iostream>
#include<stdexcept>
// a program-wIDe mutex
std::mutex TheMutex;
struct Bad {
Bad() {
std::cout<<"Attempting to get the mutex"<<std::endl;
TheMutex.lock();
std::cout<<"Got it! I'll give it to you in a second..."<<std::endl;
throw(std::runtime_error("Ooops,I threw!"));
// will never get here...
TheMutex.unlock();
std::cout<<"There you go! I released the mutex!"<<std::endl;
}
};
struct ScopedLock {
ScopedLock(std::mutex& mutex)
:m_mutex(&mutex) {
std::cout<<"Attempting to get the mutex"<<std::endl;
m_mutex->lock();
std::cout<<"Got it! I'll give it to you in a second..."<<std::endl;
}
~ScopedLock() {
m_mutex->unlock();
std::cout<<"There you go! I released the mutex!"<<std::endl;
}
std::mutex* m_mutex;
};
struct Good {
Good() {
ScopedLock autorelease(TheMutex);
throw(std::runtime_error("Ooops,I threw!"));
// will never get here
}
};
int main() {
std::cout<<"Create a Good instance"<<std::endl;
try {
Good g;
} catch (const std::exception& e) {
std::cout<<e.what()<<std::endl;
}
std::cout<<"Now,let's create a Bad instance"<<std::endl;
try {
Bad b;
} catch (const std::exception& e) {
std::cout<<e.what()<<std::endl;
}
std::cout<<"Now,let's create a whatever instance"<<std::endl;
try {
Good g;
} catch (const std::exception& e) {
std::cout<<e.what()<<std::endl;
}
std::cout<<"I am here despite the deadlock..."<<std::endl;
return 0;
}
输出(用gcc 4.8.1编译,使用-std = c 11):
Create a Good instance
Attempting to get the mutex
Got it! I'll give it to you in a second...
There you go! I released the mutex!
Ooops,I threw!
Now,let's create a Bad instance
Attempting to get the mutex
Got it! I'll give it to you in a second...
Ooops,let's create a whatever instance
Attempting to get the mutex
边栏推荐
- PostGIS learning
- 第四期SFO销毁,Starfish OS如何对SFO价值赋能?
- LinkedBlockingQueue源码分析-新增和删除
- 如何衡量产品是否“刚需、高频、痛点”
- gorm 关联关系小结
- 每日刷题记录 (十六)
- Les mots ont été écrits, la fonction est vraiment puissante!
- P1067 [noip2009 popularity group] polynomial output (difficult, pit)
- QT creator add custom new file / Project Template Wizard
- 【编程题】【Scratch二级】2019.09 绘制雪花图案
猜你喜欢
35岁那年,我做了一个面临失业的决定
关于组织2021-2022全国青少年电子信息智能创新大赛西南赛区(四川)复赛的通知
Seven years' experience of a test engineer -- to you who walk alone all the way (don't give up)
Binary sort tree [BST] - create, find, delete, output
【推荐系统基础】正负样本采样和构造
[question de programmation] [scratch niveau 2] oiseaux volants en décembre 2019
Relevant methods of sorting arrays in JS (if you want to understand arrays, it's enough to read this article)
Archery installation test
Anaconda+pycharm+pyqt5 configuration problem: pyuic5 cannot be found exe
Chisel tutorial - 05 Sequential logic in chisel (including explicit multi clock, explicit synchronous reset and explicit asynchronous reset)
随机推荐
快速回复二极管整流特性
mysql8.0 ubuntu20.4
HDU - 1260 Tickets(线性DP)
Introduction knowledge system of Web front-end engineers
Resolve the URL of token
用語雀寫文章了,功能真心强大!
Cmake learning notes (1) compile single source programs with cmake
archery安装测试
Linkedblockingqueue source code analysis - add and delete
光流传感器初步测试:GL9306
95. (cesium chapter) cesium dynamic monomer-3d building (building)
【编程题】【Scratch二级】2019.09 绘制雪花图案
Introduction to programming hardware
Chisel tutorial - 02 Chisel environment configuration and implementation and testing of the first chisel module
SQL connection problem after downloading (2)
HDU - 1260 tickets (linear DP)
Robomaster visual tutorial (0) Introduction
面试题详解:用Redis实现分布式锁的血泪史
BSS 7230 flame retardant performance test of aviation interior materials
Postgres timestamp to human eye time string or millisecond value