当前位置:网站首页>Talk about exception again -- what happens when an exception is thrown?
Talk about exception again -- what happens when an exception is thrown?
2022-06-28 13:25:00 【GarryLau】
What happens when an exception is thrown is similar to return It's kind of like
When a piece of code throws an exception , Will look in the stack catch The handler , When you find a catch The stack will release all intermediate stack frames , And go straight back to the definition catch The stack layer of the handler . Stack release (stack unwinding) This means that all destructors with locally scoped names will be called , However, when the stack is released , Pointer variables are not released , No other cleanup will be performed .
Example 1:
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <string>
namespace test_exception {
auto func2() -> void;
auto func1() -> void {
std::string str1;
std::string *str2 = new std::string();
func2();
delete str2;
}
auto func2() -> void {
std::ifstream in_file("test.txt");
throw std::exception();
in_file.close();
}
auto main() -> int {
std::cout << "testing exception..." << std::endl;
try {
func1();
}
catch(const std::exception& e) {
std::cerr << "Line " << __LINE__ << ", " << e.what() << std::endl;
return 1;
}
std::cout << "------------------------------" << std::endl;
return 0;
}
}
Example 1 Output :
__cplusplus: 201703
testing exception...
Line 35, std::exception
The end.
When func2() When an exception is thrown , The most recent exception handler is in main() in , Control immediately from func2() This line :throw std::exception(); Jump to main() This line :std::cerr << "Line " << __LINE__ << ", " << e.what() << std::endl;.
stay func2() Control is still on the line where the exception is thrown , The next line will never have a chance to run :in_file.close();. Fortunately, though , because in_file Is a local variable in the stack , So it will call ifstream Destructor ,ifstream The destructor will automatically close the file , Therefore, no resources will be disclosed here . If you dynamically allocate in_file Then this pointer will not be destroyed , The file will not be closed .
stay func1() in , Control in func2() In call to , So the next line will never have a chance to execute :delete str2;, In this case, a memory leak does occur , Stack deallocation is not automatically deleted str2, However str1 Will be properly destroyed , because str1 Is a local variable in the stack , The stack will properly destroy all local variables .
remarks : Can be combined with return Sentence comprehension .
Example 2:
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <string>
namespace test_exception {
auto func() -> void {
throw std::runtime_error("exception in func()");
}
auto testThrow1() -> auto {
std::ifstream in_file;
try {
std::string filename("testThrow.txt");
in_file.open(filename);
if(in_file.fail()) {
// This example assumes that the file is opened successfully , I won't go if Branch exception
throw std::runtime_error(filename.c_str());
}
func();
}
catch(const std::runtime_error& e) {
std::cout << "Line " << __LINE__ << ", " << e.what() << std::endl;
}
catch(...) {
std::cout << "Line " << __LINE__ << ", some exception occurs!" << std::endl;
}
// Execute the above... When an exception occurs catch Sentence block , This sentence will not be executed , But because in_file It's a local variable ,
// So it will call ifstream Destructor ,ifstream The destructor will automatically close the file , Therefore, resources will not be disclosed
// If in_file If it is dynamically allocated, the pointer will not be destroyed , The file will not be closed
in_file.close();
}
auto testThrow2() -> auto {
int *p;
try {
p = new int;
func();
}
catch(...) {
std::cout << "Line " << __LINE__ << ", some exception occurs!" << std::endl;
}
// Execute the above... When an exception occurs catch Sentence block , This sentence will not be executed , As a result, there will be a memory leak
delete p;
}
auto main() -> int {
std::cout << "testing exception..." << std::endl;
testThrow1();
testThrow2();
std::cout << "------------------------------" << std::endl;
return 0;
}
}
Example 2 Output :
__cplusplus: 201703
testing exception...
Line 24, testThrow.txt
Line 44, some exception occurs!
------------------------------
The end.
The above example shows that careless exception handling can lead to memory and resource leaks .
stay C++ You can use Intelligent pointer perhaps Capture 、 Clean up and re throw Two techniques to deal with this situation .
Use smart pointer
Smart pointer objects are allocated in the stack , Whenever smart pointer objects are destroyed , Will release the underlying resources .
Example 1 Medium func1() The function can be rewritten as :
#include <memory>
auto func1() -> void {
std::string str1;
std::unique_ptr<std::string> str2(new std::string("Hello"));
func2();
}
When from func1() When returning or throwing an exception , Will automatically delete std::string* Type of str2 The pointer .
When using smart pointers , Never have to consider freeing up the underlying resources : The destructor of the smart pointer will automatically complete this operation , This is true for both normal exit functions and exception thrown exit functions .
Capture 、 Clean up and re throw
Another technique to avoid memory and resource leaks is to make each function catch all the exceptions that may be thrown , Perform the necessary cleanup and re throw the exception for higher-level functions in the stack to handle .
Example 1 Medium func1() Can be changed to :
auto func1() -> void {
std::string str1;
std::string *str2 = new std::string();
try {
func2();
}
catch(...) {
delete str2;
throw; // rethrow the exception
}
delete str2;
}
This function is encapsulated with an exception handler func2() Call to , Handler performs cleanup ( Deleted str2) And throw the exception again .( This scheme can work well , But tedious , Two identical lines of code are required to delete str2, One line is used to handle exceptions , The other line executes when the function exits normally ).
keyword throw It will re throw any recently caught exceptions .
Use Intelligent pointer It's better than Capture 、 Clean up and re throw Technology better solutions .
Reference
1.Marc Gregoire, Nicholas A. Solter, Scott J. Kleper. C++ Advanced programming ( The first 2 edition ). tsinghua university press ,2012.(P300)
边栏推荐
猜你喜欢

Forecast and Analysis on market scale and development trend of China's operation and maintenance security products in 2022

设计人工智能产品:技术可能性、用户合意性、商业可行性

The $980000 SaaS project failed

Copy 10 for one article! The top conference papers published in South Korea were exposed to be plagiarized, and the first author was "original sin"?

Successful cases of rights protection of open source projects: successful rights protection of SPuG open source operation and maintenance platform

pytorch基础

China Database Technology Conference (DTCC) specially invited experts from Kelan sundb database to share

Solution to directory access of thinkphp6 multi-level controller

Why do more and more users give up swagger and choose apifox

真香啊!最全的 Pycharm 常用快捷键大全!
随机推荐
词云的可视化设计教程
PHP抓取网页获取特定信息
Mobile web training day-2
New product experience: Alibaba cloud's new generation of local SSD instance I4 open beta
Rk3399 platform development series explanation (use part) pinctrl subsystem introduction - Video Introduction
5A synchronous rectifier chip 20V to 12v2a/5v4.5a high current 24W high power synchronous rectifier chip high current step-down IC fs2462
Copy 10 for one article! The top conference papers published in South Korea were exposed to be plagiarized, and the first author was "original sin"?
PHP crawls web pages for specific information
How to find opportunities in a bear market?
How to solve the data inconsistency between redis and MySQL?
弹性盒子自动换行小Demo
Introduction to PWN (1) binary Basics
其他国产手机未能填补华为的空缺,苹果在高端手机市场已无对手
Recognize the startup function and find the user entry
(original) [Maui] realize "floating action button" step by step
China Database Technology Conference (DTCC) specially invited experts from Kelan sundb database to share
You must configure either the server or JDBC driver (via the ‘serverTimezone‘ configuration property
从pdb源码到frame帧对象
PHP obtains the beginning and end time of the month according to the month and year
Hubble数据库x某股份制商业银行:冠字号码管理系统升级,让每一张人民币都有 “身份证”