当前位置:网站首页>如果在构造函数中抛出异常,最好的做法是防止内存泄漏?
如果在构造函数中抛出异常,最好的做法是防止内存泄漏?
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
边栏推荐
- Chisel tutorial - 01 Introduction to Scala
- Use filters to count URL request time
- 一鍵免費翻譯300多頁的pdf文檔
- Teach you to make a custom form label by hand
- Anaconda+pycharm+pyqt5 configuration problem: pyuic5 cannot be found exe
- [the most detailed in history] statistical description of overdue days in credit
- 【编程题】【Scratch二级】2019.03 垃圾分类
- How to measure whether the product is "just needed, high frequency, pain points"
- 全自动化处理每月缺卡数据,输出缺卡人员信息
- Relevant methods of sorting arrays in JS (if you want to understand arrays, it's enough to read this article)
猜你喜欢
Laser slam learning (2d/3d, partial practice)
archery安装测试
用语雀写文章了,功能真心强大!
SQL connection problem after downloading (2)
The result of innovation in professional courses such as robotics (Automation)
Apng2gif solutions to various problems
Kubectl's handy command line tool: Oh my Zsh tips and tricks
一鍵免費翻譯300多頁的pdf文檔
Rectification characteristics of fast recovery diode
Les mots ont été écrits, la fonction est vraiment puissante!
随机推荐
机器人(自动化)等专业课程创新的结果
QT creator add JSON based Wizard
How does starfish OS enable the value of SFO in the fourth phase of SFO destruction?
Rock-paper-scissors
Ping error: unknown name or service
Robomaster visual tutorial (1) camera
Jisuan Ke - t3104
蓝桥ROS中使用fishros一键安装
Teach you to make a custom form label by hand
光流传感器初步测试:GL9306
面试题详解:用Redis实现分布式锁的血泪史
ROS from entry to mastery (IX) initial experience of visual simulation: turtlebot3
Detailed explanation of interview questions: the history of blood and tears in implementing distributed locks with redis
Set up personal network disk with nextcloud
80% of the people answered incorrectly. Does the leaf on the apple logo face left or right?
When creating body middleware, express Is there any difference between setting extended to true and false in urlencoded?
P1055 [noip2008 popularization group] ISBN number
一鍵免費翻譯300多頁的pdf文檔
Two small problems in creating user registration interface
Using Google test in QT