当前位置:网站首页>如果在构造函数中抛出异常,最好的做法是防止内存泄漏?
如果在构造函数中抛出异常,最好的做法是防止内存泄漏?
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
边栏推荐
- P1055 [noip2008 popularization group] ISBN number
- Archery installation test
- How to put recyclerview in nestedscrollview- How to put RecyclerView inside NestedScrollView?
- Detailed explanation of interview questions: the history of blood and tears in implementing distributed locks with redis
- Chisel tutorial - 01 Introduction to Scala
- Postgres timestamp to human eye time string or millisecond value
- STM32F1与STM32CubeIDE编程实例-旋转编码器驱动
- One click free translation of more than 300 pages of PDF documents
- Chisel tutorial - 00 Ex.scala metals plug-in (vs Code), SBT and coursier exchange endogenous
- 一鍵免費翻譯300多頁的pdf文檔
猜你喜欢
Les mots ont été écrits, la fonction est vraiment puissante!
[path planning] use the vertical distance limit method and Bessel to optimize the path of a star
About the difference between ch32 library function and STM32 library function
When creating body middleware, express Is there any difference between setting extended to true and false in urlencoded?
Seven years' experience of a test engineer -- to you who walk alone all the way (don't give up)
95. (cesium chapter) cesium dynamic monomer-3d building (building)
Basic learning of SQL Server -- creating databases and tables with code
Two small problems in creating user registration interface
One click installation with fishros in blue bridge ROS
Data Lake (XV): spark and iceberg integrate write operations
随机推荐
Chisel tutorial - 01 Introduction to Scala
LinkedBlockingQueue源码分析-新增和删除
AWS AWS help error
Database query - what is the highest data?
用语雀写文章了,功能真心强大!
Go learning notes (2) basic types and statements (1)
DataGuard active / standby cleanup archive settings
快速回复二极管整流特性
【编程题】【Scratch二级】2019.03 垃圾分类
蓝桥ROS中使用fishros一键安装
Open display PDF file in web page
全自动化处理每月缺卡数据,输出缺卡人员信息
The function is really powerful!
MP4文件格式解析之结合实例分析
Restricted linear table
手写一个模拟的ReentrantLock
Wechat applet development beginner 1
STM32F1与STM32CubeIDE编程实例-旋转编码器驱动
gorm 关联关系小结
Anaconda+pycharm+pyqt5 configuration problem: pyuic5 cannot be found exe