February 05, 2005
I've discovered what I think is a bug in garbage collection.  An object's constructor throws, but later on the destructor is run - it throws another exception because the data[] was never assigned to a memory slice.

The object is an MmFile object.  The simplified test case is thus:

:
:import std.mmfile;
:import std.stdio;
:import std.gc;
:
:void other_function()
:{
:    char[] pos = "A";
:
:    try {
:        pos = "A";
:        MmFile mink = new MmFile("/tmp/some/nonexistant/file");
:        pos = "B";
:    }
:    catch(Exception e) {
:        pos = pos ~ "C";
:    }
:
:    writef("pos = %s.\n", pos);
:}
:
:int main()
:{
:    int pt = 0;
:
:    try {
:        pt = 1;
:        other_function();
:        pt = 2;
:        std.gc.fullCollect();
:        pt = 3;
:    }
:    catch(Exception e) {
:        pt += 100;
:    }
:
:    writef("at pt %d.\n", pt);
:
:    return 0;
:}


Notes:

1. The problem goes away with a modified copy of the MmFile -- if the destructor
has an "if(data)" around the munmap().  This should not be necessary, because
the constructor is throwing an exception.

2. DMD version is 0.112.

3. The output from my run is:

--
open error, errno = 2
pos = AC.
at pt 102.
--

4. In other words, MmFile (which was never completely constructed) is throwing
an exception in the destructor.  I have verified this by putting a printf() in
the destructor for a modified MmFile object.

5. You can see "munmap(0,0)" in the strace() output from Linux.

Kevin




February 05, 2005
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Kevin Bealer schrieb am Sat, 5 Feb 2005 05:38:03 +0000 (UTC):
> I've discovered what I think is a bug in garbage collection.  An object's constructor throws, but later on the destructor is run - it throws another exception because the data[] was never assigned to a memory slice.
>
> The object is an MmFile object.  The simplified test case is thus:
>
>:
>:import std.mmfile;
>:import std.stdio;
>:import std.gc;
>:
>:void other_function()
>:{
>:    char[] pos = "A";
>:
>:    try {
>:        pos = "A";
>:        MmFile mink = new MmFile("/tmp/some/nonexistant/file");
>:        pos = "B";
>:    }
>:    catch(Exception e) {
>:        pos = pos ~ "C";
>:    }
>:
>:    writef("pos = %s.\n", pos);
>:}
>:
>:int main()
>:{
>:    int pt = 0;
>:
>:    try {
>:        pt = 1;
>:        other_function();
>:        pt = 2;
>:        std.gc.fullCollect();
>:        pt = 3;
>:    }
>:    catch(Exception e) {
>:        pt += 100;
>:    }
>:
>:    writef("at pt %d.\n", pt);
>:
>:    return 0;
>:}
>
>
> Notes:
>
> 1. The problem goes away with a modified copy of the MmFile -- if the destructor
> has an "if(data)" around the munmap().  This should not be necessary, because
> the constructor is throwing an exception.

Added to DStress as http://dstress.kuehne.cn/run/destructor_04.d

Thomas


-----BEGIN PGP SIGNATURE-----

iD8DBQFCBU/03w+/yD4P9tIRAvq7AJ9X1XmuCl5ggogpHDIkZ4S5KiePxgCgyHBZ
52xnUU54p3H+/SmedOrhWvU=
=uSFk
-----END PGP SIGNATURE-----