处理异常的代码称为异常安全代码?这是对的吗?
从这里开始:https://codereview.stackexchange.com/a/9759/11619
您为互斥锁使用锁定/解锁对。这不是例外。 所以我会创建一个将在构造函数中执行锁定的对象 并在析构函数中解锁然后使用它来锁定你的互斥锁。这个 将使你的代码更加安全。
class MutexLocker
{
pthread_mutex_t& mutex;
MutextLocker(pthread_mutex_t& mutex)
: mutex(mutex)
{
pthread_mutex_lock(&mutex);
}
~MutexLocker()
{
pthread_mutex_unlock(&mutex);
}
};
以上显示的代码异常以哪种方式安全?我没有在那里看到任何异常处理。
或者异常安全代码是指我们可以“添加”异常处理的地方吗?因此,通过添加异常处理可以使上面显示的代码异常安全,但现在不是吗?
答案 0 :(得分:6)
异常安全不是关于处理异常,而是即使在存在例外情况下也要保证程序的许多属性。
您通常可以谈论给定方法的exception safety level:
通常, NoThrow保证仅适用于最简单的方法(例如.size()
上的vector
)和强例外保证实施成本可能很高(能够恢复效果或对国家副本进行操作可能并不便宜)。
另一方面,基本例外保证只是:基本。没有它,安全地运行程序是不可能的,所以这是最少保证是可以接受的。如果泄漏资源或使类处于不可用状态,则程序可能无法进一步运行。
这就是为什么每当提到例外情况时都会强调RAII。因为RAII保证资源(内存,互斥体,文件)的自动清理,无论路径执行(常规返回或异常),都是特别需要的。但是,RAII本身还不够。
相关:Herb Sutter关于Exception Safety and Exception Specifications的新闻。
答案 1 :(得分:3)
总是调用MutexLocker析构函数,也就是在构造它的块中引发异常时。
这使得使用MutexLocker异常的构造安全。
答案 2 :(得分:3)
您不必处理异常是异常安全的。你只需要在抛出异常时生存。
MutexLocker可帮助您在离开示波器时解锁互斥锁。如果您通过return语句离开或抛出异常并不重要。
答案 3 :(得分:2)
“异常安全”是一个相当重载的术语,但我会用它来描述可以通过它们抛出异常的代码部分,并且仍然保持某些不变量(例如 - 没有任何变化,没有资源被泄露,所有对象保持不变一个有效的州。)
例如,您的void * printHello (void* threadId)
函数是正确的(因为它始终与pthread_mutex_lock (&demoMutex)
匹配pthread_mutex_unlock (&demoMutex)
),但如果有人更改了中间的部分,那么它可以抛出一个异常(例如,通过在std::cout
上设置throw标志),然后您的代码将永久锁定demoMutex
,并且没有希望它被释放。这将构成您程序中的错误。 void * printHello (void* threadId)
被称为“异常不安全”,因为通过向看似无关的部分添加异常处理,可以很容易地将错误引入程序中。
使用RAII类来管理资源是编写异常安全代码的一种好方法(并且 资源管理风格在C ++中使用),因为它避免了重复手动清理的需要catch(...)
阻止,并通过使用类型系统强制清理资源。
答案 4 :(得分:1)
处理异常的代码称为异常安全代码?
是的,但你没说好。 This是关于异常安全的好读物。
以上显示的代码异常以哪种方式安全?
该代码本身并非异常安全。这意味着要在异常安全的代码中使用。例如:
void bar()
{
throw std::runtime_error( "lala" );
}
void foo()
{
pthread_mutex_lock(&mutex);
bar();
// OPS! mutex not unlocked
pthread_mutex_unlock(&mutex);
}
使用自动解锁异常的类可以解决此问题。下一个示例具有强有力保证的异常处理:
void foo()
{
MutexLocker locker( mutex );
try {
bar();
} catch ( const std::runtime_error & )
{
// revert changes
}
}
答案 5 :(得分:0)
您提供的代码很有用。简单地说,当执行离开定义MutexLocker
对象的块时,对象将被销毁,并且根据其析构函数释放互斥锁。无论出口的原因如何,这都有效。
你不必自己编写这门课程。 C ++标准指定了一个名为lock_guard
的类,它正是这样做的。