投掷dtors ... [英] throwing dtors...

查看:86
本文介绍了投掷dtors ...的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

投掷dtor是否合适?我正在考虑一个简单的

POSIX文件包装器的例子...

__________________________________________________ ______________________

类文件{

FILE * m_handle;


public:

// [...];


~file()/ * throw()* / {

int const status fclose(m_handle);

if(status){

/ * shi%击中粉丝:
http:/ /www.opengroup.org/onlinepubs/...sh/fclose.html

/ *


// [现在怎么样?]

}

}

};

__________________________________________________ ______________________

如何妥善处理EAGAIN在dtor?好吧,那个

的错误呢?我是一名C程序员,只有代码C ++才有趣,还有一些内部

项目。如果我真的要创建C ++应用程序并将其发布到野外,那么,您如何建议我处理上述情况?我对

感兴趣如何投入dtor效果动态破坏......会不会像以下那样合法?


<伪代码!!!!>

__________________________________________________ _____________

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; }

};


类文件{

文件* m_handle;


公开:

// [ctor];


~file(){

int const status = fclose(m_handle);

if(status){

throw throw_from_dtor(status);

}

}

};

int main(){

file * f =新文件();

试试{

删除f;

} catch(throw_from_dtor const& e){

//来自`e.get_status()的错误处理''

删除f;

}

返回0;

}

__________________________________________________ _____________



或者如何使用智能指针...


int main(){

std :: auto_ptr< filef;

尝试{

f.reset(new file());

} catch(throw_from_dtor const& e){

//处理来自`e.get_status()的错误''

}

}






请记住,拒绝不处理来自fclose的错误可能

resule是可怕的事情......想想大量的数据丢失......

也许__permanent__数据 - !哦!!!


; ^ /

解决方案



Chris M. Thomasson < no@spam.invalidwrote in message

news:k4 ****************** @ newsfe06.iad ...
< blockquote class =post_quotes>
是否适合扔进dtor?我正在考虑一个简单的

POSIX文件包装器的例子...

__________________________________________________ ______________________



[...]


__________________________________________________ ______________________


如何正确处理dtor中的'EAGAIN'?那么,

的任何错误怎么回事?我是一名C程序员,只是为了好玩而编写C ++代码,以及一些内部项目的b
。如果我真的要创建C ++应用程序并且

将它释放到野外,那么,您如何建议我处理上面的案件

?我感兴趣的是如何投入dtor效果动态

破坏...以下类似的东西是合法的吗?


<伪代码!!! !>

__________________________________________________ _____________

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; }

};


类文件{

文件* m_handle;


公开:

// [ctor];


~file(){

int const status = fclose(m_handle);

if(status){

throw throw_from_dtor(status);



^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^^^^^^^^


//嗯!好吧,愚蠢的我忘了把'errno''存入

异常!!!!!!


throw throw_from_dtor(errno);


//对不起感到抱歉! ; ^(...


}

}

};



int main(){

file * f = new file();

try {

删除f;

} catch(throw_from_dtor const& e){

//来自`e.get_status()的错误处理''
删除f;

}

返回0;

}

__________________________________________________ _____________





或者使用智能指针怎么样......


int main(){

std :: auto_ptr< filef;

尝试{

f.reset(new file());

} catch(throw_from_dtor const& e){

//处理来自`e.get_status()的错误''

}

}





请记住拒绝不处理来自`fclose'的错误

复活是可怕的事情在路上...想想海量数据

输了......也许__permanent__数据 - !哦!!!


; ^ /


" Chris M. Thomasson" < no@spam.invalidwrote in message

news:k4 ****************** @ newsfe06.iad ...
< blockquote class =post_quotes>
是否适合扔进dtor?我正在考虑一个简单的

POSIX文件包装器的例子...

__________________________________________________ ______________________



[...]


__________________________________________________ ______________________



[...]
< blockquote class =post_quotes>
您如何建议我处理上述案例?我感兴趣的是

如何投入dtor效果动态破坏...

后面的东西是合法的吗?



[...]


我正在做一些实验,发现从一个dtor投掷

显然使对象完全无损可以实现正确的灾难清理的内存......例如,

跟随程序进入无限循环:

__________________________________________________ ____________________

#include< cstdio>


struct throw_on_dtor {};


class foo {

public:

~foo(){

throw throw_on_dtor();

}

};


int main(无效){

foo * f = new foo();

重试:

尝试{

删除f;

} catch(throw_on_dtor const& e){

std :: puts(throw_on_dtor抓住了! );

goto重试;

}

返回0;

}


__________________________________________________ ____________________


因此,AFAICT从dtor投掷会使一些奇怪的并发症复杂化。

然而,他们可以一定要好好解决。事实上,dtor可以抛出
,这确实需要记录清楚。当文件关闭被信号

(例如,'EINTR'')中断时,上述高度粗略的技术

可用于解决这一事实。它也可以用来处理'EAGAIN''......虽然,当你处理一个可以从它的b $ b抛出一个类的类时,它似乎更容易使用新的位置dtor,这样catch块实际上可以释放内存

而无需再次运行dtor就像删除那样...类似于:


__________________________________________________ ____________________
#include< cstdio>

#include< cstdlib>

#include< new>


struct throw_on_dtor {};


class foo {

public:

~foo(){

throw throw_on_dtor();

}

};


int main(无效){

foo * f = new(std :: malloc(sizeof(* f)))foo();

if(f){

retry:

尝试{

f-> ~foo();

std :: free(f);

} catch (throw_on_dtor const& e){

std :: puts(" throw_on_dtor caught!Handling Error ...");

std :: free(f);

}

}

返回0;

} < br $>
__________________________________________________ ____________________


Humm ......放置新的灵魂看起来非常适合投掷

dtors!


此外,从dtors抛出的一个类可以包含一个dtor计数器和/或

标志来检测dtor被调用了多少次(如果有的话);一些东西

喜欢:


class foo {

unsigned m_dtor_invoke; // = 0

bool m_dtor_throw; // = false;

public:

~foo(){

++ m_dtor_invoke;

if( !m_dtor_throw){

m_dtor_throw = true;

throw throw_on_dtor();

}

}

};


有什么想法吗?顺便说一句,尽量不要过于严厉地惹我生气!我试图避免

用户显式调用一个关闭函数...或者,这是一个很好的主意

处理任何有一个dtor调用一个类的类可能失败的API

_AND_这样的失败表示重要的事情?

; ^(......


< blockquote>

" Chris M. Thomasson"< no@spam.invalidwrote in message

news:ao ************* ***** @ newsfe06.iad ...


" Chris M. Thomasson"< no@spam.invalidwrote in message

news:k4 ****************** @ newsfe06.iad ...


>是吗什么都适合投入dtor?我正在考虑一个简单的例子来围绕POSIX文件的包装......
_________________________________________________ _______________________



[...]


> __________________________________________ _______ _______________________



[...]


>您如何建议我处理此案以上?我感兴趣的是如何投入dtor效果动态破坏......以下是否合法?



[.. 。]


我正在做一些实验,并发现从一个dtor投掷

显然会使对象完全完好无损的内存。 />
以便确实可以执行适当的灾难清理...例如,

以下程序进入无限循环:

__________________________________________________ ____________________
#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){< br $> 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 simple
example 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 that
matter? I am a C programmer and only code C++ for fun, and some in-house
projects. If I were really going to create C++ application and release it
into the wild, well, how would you advise me to handle the case above? I am
interested in how throwing in a dtor effects dynamic destruction... Would
something 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'' could
resule is HORRIBLE things down the road... Think massive data lost...
Perhaps __permanent__ data-! OUCH!!!

;^/

解决方案


"Chris M. Thomasson" <no@spam.invalidwrote in message
news:k4******************@newsfe06.iad...

Is it every appropriate to throw in a dtor? I am thinking about a simple
example of a wrapper around a POSIX file...
__________________________________________________ ______________________

[...]

__________________________________________________ ______________________
How to properly handle `EAGAIN'' in dtor? Well, what about any error for
that matter? I am a C programmer and only code C++ for fun, and some
in-house projects. If I were really going to create C++ application and
release it into the wild, well, how would you advise me to handle the case
above? I am interested in how throwing in a dtor effects dynamic
destruction... Would something 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);

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^

// ummmm! well, stupid me forgot to store `errno'' into the
exception!!!!!!

throw throw_from_dtor(errno);

// sorry about the non-sense! ;^(...

}
}
};


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''
could resule is HORRIBLE things down the road... Think massive data
lost... Perhaps __permanent__ data-! OUCH!!!

;^/


"Chris M. Thomasson" <no@spam.invalidwrote in message
news:k4******************@newsfe06.iad...

Is it every appropriate to throw in a dtor? I am thinking about a simple
example of a wrapper around a POSIX file...
__________________________________________________ ______________________

[...]

__________________________________________________ ______________________

[...]

how would you advise me to handle the case above? I am interested in how
throwing in a dtor effects dynamic destruction... Would something like the
following be legal?

[...]

I am doing some experimenting, and found that throwing from a dtor
apparently leaves the object fully intact wrt the memory that makes it up so
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.
However, they can be worked out for sure. This fact that a dtor can throw
will need to be CLEARY documented indeed. The above highly crude technique
can 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, it
seems eaiser to use placement new when your dealing with a class that can
throw from its dtor, so that the catch block can actually free memory
without 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 throwing
dtors indeed!

Also, a class which throws from dtors could contain a dtor counter and/or
flag to detect how many times, if any, the dtor has been invoked; something
like:

class foo {
unsigned m_dtor_invoke; // = 0
bool 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 the
user explicitly calling a close function... Or, is that a great idea wrt
dealing with any class that has a dtor which calls an API that can fail
_AND_ such failure indicates something important?
;^(...



"Chris M. Thomasson" <no@spam.invalidwrote in message
news:ao******************@newsfe06.iad...

"Chris M. Thomasson" <no@spam.invalidwrote in message
news:k4******************@newsfe06.iad...

>Is it every appropriate to throw in a dtor? I am thinking about a simple
example of a wrapper around a POSIX file...
_________________________________________________ _______________________

[...]

>_________________________________________________ _______________________

[...]

>how would you advise me to handle the case above? I am interested in how
throwing in a dtor effects dynamic destruction... Would something like
the following be legal?

[...]

I am doing some experimenting, and found that throwing from a dtor
apparently leaves the object fully intact wrt the memory that makes it up
so 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 error
handling should be preformed within dtor... However, what if user wants to
be informed of any failure case within dtor? Should I provide a simple
callback 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 ...的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆