[Issue 6186] Struct destructor is not called on out parameter

d-bugmail at puremagic.com d-bugmail at puremagic.com
Fri Sep 20 06:22:47 PDT 2013


http://d.puremagic.com/issues/show_bug.cgi?id=6186


monarchdodra at gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |monarchdodra at gmail.com


--- Comment #4 from monarchdodra at gmail.com 2013-09-20 06:22:43 PDT ---
I just hit this. This is my use case, and it's causing a leak:

//----
struct S
{
    this(int)  {writeln("constructor");}
    ~this()    {writeln("destructor");}
}
alias RefCounted!S RCS;

void foo(out RCS){}

void main()
{
    auto rcs = RCS(5); //Use my variable.
    foo(rcs); //Re-use my variable
}
//----
Output:
constructor

EG: It leaked.

Walter says:

> Out variables are supposed to be initialized by the function, not assigned.
> Hence, I think uninitialized variables should be passed to them, and it should
be an error to pass a non-default-initialized variable.

It was my understanding that the entire *point* of "out" was that the
*language* initialized the parameter, both for the function (no need to test
the variable is in an initial state), and the caller (no need to (re)-set to
initial state).

Overwriting a variable without first destroying it is always wrong behavior,
and unsafe. It should not be out's default behavior.

If you insist that the correct behavior is that an out parameter must not be
initialized beofre use, then "out"'s correct behavior should instead be to
verify the passed argument already has the T.init value, and assert otherwise.

In his pull:
https://github.com/D-Programming-Language/dmd/pull/155
Kenji says:

> Sure. It was out of consideration about void-initialized variable.
> But, calling dtor before passing to out parameter is still 'right semantic' for initialized variable. To separate cases, we should detect statically that the variable is initialized or not.

D specs says that "uninitialized" has the value of T.init, and T.init must
*always* be destroyable, so that is not an issue, IMO. void-initialization is a
user-explicit unsafe state we should not have to bother supporting.

Also, how hard is it to detect the two scenarios?
//----
void foo(out T);
void main()
{
    T t;
    foo(t); //t was *just* decalred, No need to re-initialize
}
//----

Or
//----
void bar(out T t)
{
    foo(t); //t is already out, so no need to re-initialize
}
//----

IMO, the first case represents the majority of "out" usage, and the second an
interesting optimization.

In every other case, we can re-initialize.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list