www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 2895] New: std.stream.File access violation on close() in dtor

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2895

           Summary: std.stream.File access violation on close() in dtor
           Product: D
           Version: 2.029
          Platform: PC
        OS/Version: Windows
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla digitalmars.com
        ReportedBy: steve.teale britseyeview.com


import std.stream;

class XXX
{
   std.stream.File _log;
   int _logLevel;
   uint _maxsize;
   uint _maxfiles;
   int _numlogs;
   bool _ok;
   int _cycle;

   this()
   {
      _log = new std.stream.File(r"d:\dcat\test.log",
std.stream.FileMode.Append);
   }

   ~this()
   {
      _log.close(); 
   }

}

void main()
{
   XXX log = new XXX();
}
/*
D:\dcat\bevutils>examp
An exception was thrown while finalizing an instance of class examp.XXX

object.Error: Access Violation
*/

The strange thing is that if I comment out any of the unused class member
variables, the problem goes away.


-- 
Apr 25 2009
parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2895


fvbommel wxs.nl changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |INVALID





This is a bug in your code.
Don't access GC-allocated memory from the destructor unless you're sure it
won't be collected before the destructor is called. In this case, the likely
sequence of events when the GC runs on program exit is as follows:

1) The GC sees the File is no longer referenced from any root, and frees its
memory pool slot.
2) Since it was the last (only) item in its memory pool, the memory for the
pool gets unmapped.
3) The GC determines there are no more references to your XXX.
4) The GC first calls the destructor for the XXX.
5) The destructor accesses unmapped memory (previously known as a File) and
triggers an access violation.

If you shrink the XXX class by removing members, it probably shrinks enough to
be put into the same pool as the File object (which is presumably smaller).
This causes the File to no longer be the last item in its memory pool just
before it gets collected, so the pool is not freed yet. The XXX destructor then
accesses deallocated (but not unmapped) memory before returning and letting the
program close down gracefully, without detecting the bug.


-- 
Apr 25 2009