C++安全的异常处理
C++ Safe Exception Handling
让我们有一段代码(fstream只是一个例子,我们可以谈论动态内存分配...):
fstream f;
try {
f.open("xxx");
...
f.close();
} catch (...) {
...
}
当出现问题时,我想关闭()文件(释放内存或其他什么),但我不知道f的状态。毕竟,异常可能来自 f.open()。我认为在 catch 子句中调用 f.close() 是不安全的,因为我不能再相信 f。
f 也可以是指向动态分配数组的指针,我想删除 [],但谁知道在抛出异常后它指向哪里......
这可能不是很常见,但是当我绝对无法承受任何额外的伤害时,我该怎么办?
我可以考虑立即中止()。
谢谢。
您应该使用 RAII 或此处通常称为 SBRM(基于范围的资源管理):)
fstream
析构函数为你调用close
。引发异常时,文件将自动关闭。
对于管理内存,您可以使用智能指针。
为了管理互斥锁或更通用的锁,大多数库都为您提供了一个类,其析构函数为您解锁互斥锁。
切勿以以下形式编写代码:
acquire a resource
do stuff which can throw
release a resource
请改用其析构函数为您释放资源的对象。
fstream 析构函数将为你调用 close(),所以你真的不需要自己关闭它(除非你想看到 close() 的返回代码)。
在您的示例中,您可以将 f
声明移动到 try
块中以确保它自行销毁;析构函数知道对象的状态。
再举一个例子,对于内存分配,您可以在实际分配内存之前将指针初始化为 0,然后在释放分配的内存时再次将其重置为零。这使您可以检查是否分配了内存以避免释放不再属于您的内存。例:
char *name = 0;
try {
// perform some operations which may throw...
// now allocate
name = new char[20];
// more error prone operations here
}
catch(...){
if(name != 0){
delete[] name;
name = 0;
}
}
同样,您也可以在此处使用 RAII。例:
class MyCharArray {
char *str;
public:
MyCharArray(size_t size){
str = new char[size];
}
~MyCharArray(){
delete[] str;
}
};
int main(){
try {
// perform some operations which may throw...
MyCharArray name(20);
// more error prone operations here
}
catch(...){
// no additional error handling required here
}
return 0;
}
请注意,RAII 被认为是优越的,因为您只编写一次清理代码 - 在析构函数中 - 而不是在每个try
块之后。
在 fstream 对象上启用异常,并在可能的位置处理异常:
void foo()
{
std::fstream f( "lala.txt" );
f.exceptions( std::fstream::failbit | std::fstream::badbit )
// do something
}
我不认为使用 boost 来做 RAII 是作弊:
#include <boost/smart_ptr.hpp>
#include <fstream>
using namespace std;
static void do_close(fstream* f)
{
try
{
f->close();
delete f;
} catch(...) { /* log the error? */ }
}
int main()
{
boost::shared_ptr<fstream> f(new fstream(), &do_close);
try
{
f->open("xxx");
f->close();
} catch (...)
{
}
}
- 为什么我应该在异常处理中使用std::cerr而不是std::cout
- 当我使用 C++ 中的 C# dll 来使用 Selenium 时,存在异常处理问题
- Firebase C++VS2018 SDL2-在Firebase::app::create(..)上执行异常处理
- 使用 stoi 功能进行异常处理
- 子系统中的异常处理:本机
- 与异常处理程序中的操作员<<不匹配
- 数组 C++ 上的异常处理程序
- 异常处理:如果用户输入不是三个特定字符之一
- C++ 异常处理错误输出
- 视觉 std::矢量无异常:警告 C4530:使用了C++异常处理程序,但未启用展开语义.指定 /EHsc
- C++交换机状态异常处理
- 在字符串类上的成员函数和out_of_range异常处理
- 奇怪的消息 (_Base_bitset::_M_do_to_ulong) 从溢出异常处理程序中打印出来
- 执行视觉工作室异常处理模式
- 为什么隐式转换在异常处理中从派生到基?
- C++执行期间的类成员函数错误/异常处理
- C++ 中未处理的异常处理程序
- 用户定义的异常处理
- X 的错误处理程序抛出异常是否安全?
- C++安全的异常处理