C++/Exception Training

Wolf0403 2007-05-25 08:29:39
Effectively Using C++
Object Management., RAII and Exception

by Ryan Gao
...全文
659 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
chenhu_doc 2007-05-26
  • 打赏
  • 举报
回复
废人,非人呢!
lin_style 2007-05-25
  • 打赏
  • 举报
回复
E文翻译中
。。
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
The end..
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
Reference
---

[D.Abrahams ESGC] David Abrahams, "Exception-Safety in Generic Components", http://www.boost.org/more/generic_exception_safety.html
[S.Meyers, 2005] Scott Meyers, "Effective C++"
[B.Stroustrup, 2000] Bjarne Stroustrup, "The C++ Programming Language, Special Edition"
Jackson Sun, "如何编写异常安全的C++代码"
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
The trick shown above, using class to manage the lifecycle of an raw resource is generally referred as RAII in the C++ community.
RAII stands for "Resource Acquisition Is Initialization".
std::auto_ptr<T> is generally an demonstration of RAII in the standard library.
Containers from the STL expects its containing objects has the normal value semantics, low cost of copying and destructing. Unfortunately std::auto_ptr has its unusual copy semantics hence CAN'T be used in STL containers.
If desired, use tr1::shared_ptr (formally boost::shared_ptr) for unsuitable RAII classes, or make it an light, normal value class instead.
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
STL the Standard Template Library has settled the style of C++ language in general use (in certain degree)
Upon exceptions, there are styles and no-throw guarantees followed by STL compatible classes:
Value semantics (copy constructor and operator= must be implemented, right)
no-throw for destructor and swap() if provided. Specialize std::swap function template recommended over member swap() function. [S.Meyers, 2005]
Extensively use of const interface
Extensively use const-ref for parameter passing, use PBV in case const-ref won't serve the purpose.
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
class T {
T (T const& t) { member.swap(t.member); }
T const& operator= (T const& t) {
this->swap(T(t));
}
void swap (T &t) {
std::swap (member, t.member);
}
OtherType const& getSomeProperty () const {
}
};
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
The STL Style (from Pool_Handle slide)

---

The class ResourceNs has taken the responsibility taking care of the "raw" resources, i.e. network sockets, database connections, etc.
Java GC only works with memory. Other resources are required to be managed manually (e.g. .close() of all those *Streams). That means the ResourceNs are not implementable in Java reasonably. Hence...
The Java equivalent is just far toooooo lengthy to fit on this slide...
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
{ // pretending in a constructor, allocating resource for members
// remember the C-style code?
std::auto_ptr<R1> p1 (new Resource1());
std::auto_ptr<R2> p2 (new Resource2());
std::auto_ptr<R3> p3 (new Resource3());
this->pR1 = p1.release();
this->pR2 = p2.release();
this->pR3 = p3.release();
// last 3: std::auto_ptr's ops are
// compliant to the no-throw guarantee
}
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
The magic is all within the *_Handle classes. A simple example here
struct FPPool_Handle {
FPPool_Handle(FPPoolRef const& h)
: handle_(h)
{}
~FPPool_Handle ()
{ FPPool_Close(handle_); }
private:
FPPoolRef handle_;
};
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
Pool_Handle pool (getPool());
Clip_Handle clip (getClip(pool));
doWhatEverYouLike();
// and that's much of it
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
Dirty Java style, procedural exception polluted code...
FPPool pool = null;
FPClip clip = null;
try {
pool = getPool();
clip = getClip(pool);
someOtherOpThatMightThrow();
} finally {
if (clip != null)
{ try {clip.Close();} catch (Throwable t) { /**/ }
if (pool != null)
{ try {pool.Close();} catch (Throwable t) { /**/ }
}
I started to miss #define already...
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
Dirty, C-style, procedural code with no exception...
int h1, h2, h3;
if (h1 = alloc_resource1()) < 0) goto fail_r1;
if (h2 = alloc_resource2()) < 0) goto fail_r2;
if (h3 = alloc_resource3()) < 0) goto fail_r3;
return OK;
fail_r3:
release_resource2(h2);
fail_r2:
release_resource1(h1);
fail_r1:
return FAIL;
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
Basic guarantee for all operations:
The invariants of the component are preserved,
and no resources are leaked. [D.Abrahams ESGC]
Strong guarantee for key operations:
The operation has either completed successfully or thrown an exception, leaving the program state exactly as it was before the operation started. [D.Abrahams ESGC]
The no-throw guarantee:
The operation will not throw an exception.
[D.Abrahams ESGC]
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
As mentioned before, any instruction in the same block bellow won't get executed
Problem:
char* buffer = new char[N];
tendToGetSoInsecure(buffer); // when throw
delete[] buffer; // no one will touch here..
We need our code "exception-safe"
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
Expected (standard) exceptions:
std::bad_alloc if new failed
std::bad_cast if dynamic_cast failed
More. Check them out from Section 14.10 "Standard Exceptions" [B.Stroustrup 2000]
Remember: All C++ exceptions are EXPECTED!!!
Accessing NULL / wild pointers will NOT cause an C++ exception hence can't be catched!!
Unix signals / Win32 SEH are NOT C++ exceptions!!
If you want to catch something, make sure someone is throwing it.
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
Recommended exception handling
Throw by value, catch by reference.
Exception may have class hierarchies, catch by reference will allow to handle a "class" of exceptions all together.
try clause may have multiple catch clauses followed and is selected in an "first match" matter so sequence matters!
catch (...) means generally the same as
catch (Throwable t) in Java. Information of caught exception is lost within this catch clause.
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
So, What's so COOOOOOL about stack unwinding?
All auto variable have their ~T() called
Manually manipulated (newed, fopened, etc) resources untouched to guarantee the free will of programmer.
Control flow handled back to the caller.
Program kept in "exception handling" state, so caller need no special treatment if don't know what to do.
All automated process.
Have global fall-back mechanism and can be customized (std::set_terminate).
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
So, let's do it the unexpected way.
throw std::exception();
What will happen?
Normal execution flow interrupted (any instruction in the same block bellow won't get executed)
Looking for corresponding catch clause, unwinding stack if not found
std::terminate() called if uncaught at all.
Wolf0403 2007-05-25
  • 打赏
  • 举报
回复
More problems
Error in nested loops / nested function calls
Can't chain up function calls
outer (inner()); /* How do we handle failure in inner() ? */
Messes up error handling flow with normal logic
Not everyone knows how to handle every error, but redundant logic must present
if ( FAILED == lastReturnValue ) {
return error_indicator;
}
加载更多回复(11)

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧