#include< cstdio> struct throw_on_dtor {}; class foo { $ b $公开: ~foo(){ throw throw_on_dtor(); } }; int main(无效){ foo * f = new foo(); 重试: 尝试{ 删除f; } catch(throw_on_dtor const& e){ std :: puts(" throw_on_dtor caught!&q uot;); goto重试; } 返回0; } __________________________________________________ ____________________ 因此,AFAICT从dtor投掷会使一些奇怪的并发症复杂化。 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^ 让我改写一下: 所以,AFAICT,从dtor投掷会产生一些奇怪的并发症...... Humm ......我现在想的是,不是从dtor投掷,所有错误 处理应该在dtor中执行...但是,如果用户想要 被告知dtor内的任何失败案例?我应该提供一个简单的 回调函数来通知用户这种情况吗?类似于: __________________________________________________ _________ 班级档案{ FILE * m_handle; bool(* m_fp_on_dtor_error)( file&,int); public: foo(fp_on_dtor_error fp = NULL) :m_fp_on_dtor_error(fp){ b $ b [...] }; ~foo(){ 重试: if(!fclose(m_handle)){ if(m_fp_on_dtor_error){ if(m_fp_on_dtor_error(* this,errno)){ goto重试; } } } } }; __________________________________________________ _________ 嗯......我需要建议! ; ^ o Is it every appropriate to throw in a dtor? I am thinking about a simpleexample of a wrapper around a POSIX file...__________________________________________________ ______________________class file {FILE* m_handle;public:// [...];~file() /* throw() */ {int const status fclose(m_handle);if (status) {/* shi% hit the fan: http://www.opengroup.org/onlinepubs/...sh/fclose.html/*// [what now?]}}};__________________________________________________ ______________________How to properly handle `EAGAIN'' in dtor? Well, what about any error for thatmatter? I am a C programmer and only code C++ for fun, and some in-houseprojects. If I were really going to create C++ application and release itinto the wild, well, how would you advise me to handle the case above? I aminterested in how throwing in a dtor effects dynamic destruction... Wouldsomething like the following be legal?<pseudo code!!!!>__________________________________________________ _____________struct throw_from_dtor {int const m_status;public:throw_from_dtor(int const status)m_status(status) {}int get_status() const { return m_status; }};class file {FILE* m_handle;public:// [ctor];~file() {int const status = fclose(m_handle);if (status) {throw throw_from_dtor(status);}}};int main() {file* f = new file();try {delete f;} catch(throw_from_dtor const& e) {// handle error from `e.get_status()''delete f;}return 0;}__________________________________________________ _____________?or what about using smart pointer...int main() {std::auto_ptr<filef;try {f.reset(new file());} catch(throw_from_dtor const& e) {// handle error from `e.get_status()''}}?Please keep in mind that refusing to not handle an error from `fclose'' couldresule is HORRIBLE things down the road... Think massive data lost...Perhaps __permanent__ data-! OUCH!!!;^/ 解决方案[...]^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^// ummmm! well, stupid me forgot to store `errno'' into theexception!!!!!!throw throw_from_dtor(errno);// sorry about the non-sense! ;^(...[...][...][...]I am doing some experimenting, and found that throwing from a dtorapparently leaves the object fully intact wrt the memory that makes it up sothat proper disaster cleanup can indeed be performed... For example, thefollowing program goes into infinite loop:__________________________________________________ ____________________#include <cstdio>struct throw_on_dtor {};class foo {public:~foo() {throw throw_on_dtor();}};int main(void) {foo* f = new foo();retry:try {delete f;} catch (throw_on_dtor const& e) {std::puts("throw_on_dtor caught!");goto retry;}return 0;}__________________________________________________ ____________________So, AFAICT, throwing from a dtor will complicate some odd complications.However, they can be worked out for sure. This fact that a dtor can throwwill need to be CLEARY documented indeed. The above highly crude techniquecan be used to solve the fact when a file close is interrupted by a signal(e.g., `EINTR''). It can also be used to handle `EAGAIN''... Although, itseems eaiser to use placement new when your dealing with a class that canthrow from its dtor, so that the catch block can actually free memorywithout running the dtor again like delete does... Something like:__________________________________________________ ____________________#include <cstdio>#include <cstdlib>#include <new>struct throw_on_dtor {};class foo {public:~foo() {throw throw_on_dtor();}};int main(void) {foo* f = new (std::malloc(sizeof(*f))) foo();if (f) {retry:try {f->~foo();std::free(f);} catch (throw_on_dtor const& e) {std::puts("throw_on_dtor caught! Handling Error...");std::free(f);}}return 0;}__________________________________________________ ____________________Humm... The placement new soultion looks like a good match for throwingdtors indeed!Also, a class which throws from dtors could contain a dtor counter and/orflag to detect how many times, if any, the dtor has been invoked; somethinglike:class foo {unsigned m_dtor_invoke; // = 0bool m_dtor_throw; // = false;public:~foo() {++m_dtor_invoke;if (! m_dtor_throw) {m_dtor_throw = true;throw throw_on_dtor();}}};Any thoughts? BTW, try not to flame me too harshly! I am trying to avoid theuser explicitly calling a close function... Or, is that a great idea wrtdealing with any class that has a dtor which calls an API that can fail_AND_ such failure indicates something important?;^(...[...][...][...]I am doing some experimenting, and found that throwing from a dtorapparently leaves the object fully intact wrt the memory that makes it upso that proper disaster cleanup can indeed be performed... For example,the following program goes into infinite loop:__________________________________________________ ____________________#include <cstdio>struct throw_on_dtor {};class foo {public: ~foo() { throw throw_on_dtor(); }};int main(void) { foo* f = new foo();retry: try { delete f; } catch (throw_on_dtor const& e) { std::puts("throw_on_dtor caught!"); goto retry; } return 0;}__________________________________________________ ____________________So, AFAICT, throwing from a dtor will complicate some odd complications.^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^let me rephrase:So, AFAICT, throwing from a dtor will _create_ some odd complications...Humm... I am now thinking that instead of throwing from dtor, all errorhandling should be preformed within dtor... However, what if user wants tobe informed of any failure case within dtor? Should I provide a simplecallback function to inform user of such condition? Something like:__________________________________________________ _________class file {FILE* m_handle;bool (*m_fp_on_dtor_error) (file&, int);public:foo(fp_on_dtor_error fp = NULL): m_fp_on_dtor_error(fp) {[...]};~foo() {retry:if (! fclose(m_handle)) {if (m_fp_on_dtor_error) {if (m_fp_on_dtor_error(*this, errno)) {goto retry;}}}}};__________________________________________________ _________Humm... I need ADVISE!;^o 这篇关于投掷dtors ...的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
07-30 22:16