|
Boost : |
From: Mike Tegtmeyer (tegtmeye_at_[hidden])
Date: 2007-11-02 19:00:12
Good answer
The common retort from new folks that I hear to the "no attempt to
interpret the pointer value" argument is more of a pragmatic one: it
doesn't behave as expected in the fundamental case. I appreciate the other
side of the coin awkward trick example however, and as I sit and think
about it - that is much more painful.
The counter argument that I hear from not-new folks however is that it
takes some work to not leak the resource during an exception in the
shared_ptr construction. Therefore, the ugliness to maintain integrity
diminishes it's usefulness. ie
FILE *in = fopen(...);
if(!in)
return/throw badness;
//may throw here, 'in' is lost
shared_ptr<FILE> fin(in,fclose);
Therefore,
<third_person>
struct file_sentry {
file_sentry(FILE *_f) :f(_f) {}
~file_sentry() { if(f) fclose(f); }
FILE *f;
};
file_sentry sentry(fopen(...));
if(!sentry.f)
return/throw badness;
//if throw here, 'in' gets closed
shared_ptr<FILE> fin(sentry.f,fclose);
sentry.f = 0;
But gee, that was a lot of work, maybe if I just refactor file_sentry to
resource_sentry so it does what I want...
- or -
shared_ptr<file_sentry> ... do I really have to call new here???
- will maybe if I point shared_pointer to a local object, eh my head
hurts, never mind, exception safety is just mental gymnastics anyway...
</third_person>
I can understand the frustration.
Mike
On Sat, 3 Nov 2007, Peter Dimov wrote:
> Mike Tegtmeyer:
>
>> I am often asked why shared_ptr always uses the custom deleter even when
>> the pointer argument is zero. I know it is safe to delete a NULL pointer
>> so this works with delete but it would seem that if the user is giving a
>> custom deleter, then they are probably doing something else. ie
>>
>> //will crash if fread returns 0
>> shared_ptr<FILE> foo(fread("foo.txt","r"),fclose);
>
> This is a good question without an easy answer. There is a conflict between
> semantical purity (shared_ptr does not attempt to interpret the pointer
> value in any way, this task is left to the deleter and ultimately to the
> programmer) and expressive power (the user may, in fact, want his deleter to
> be called even for NULL) on one side, and convenience for use cases like
> fopen, on the other.
>
> Neither alternative is a clear winner. What tips the scales somewhat is that
> (a) typically an idiomatic C++ wrapper over FILE would not construct a
> shared_ptr when fopen fails, it will throw an exception, (b) many resource
> releasing functions (such as 'free') do ignore NULLs instead of crashing,
> and (c) there is a relatively easy (if inconvenient) workaround.
>
> (If shared_ptr didn't call the deleter for NULLs, one would have to use
> somewhat awkward tricks such as encode NULL as (void*)-1 in the reverse
> case.)
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk