[Issue 4613] New: temporary generated inside foreach is not correctly destructed

d-bugmail at puremagic.com d-bugmail at puremagic.com
Tue Aug 10 08:54:35 PDT 2010


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

           Summary: temporary generated inside foreach is not correctly
                    destructed
           Product: D
           Version: D2
          Platform: Other
        OS/Version: Mac OS X
            Status: NEW
          Severity: major
          Priority: P2
         Component: DMD
        AssignedTo: nobody at puremagic.com
        ReportedBy: andy at aligature.com


--- Comment #0 from andy at aligature.com 2010-08-10 08:54:33 PDT ---
Using dmd v2.047 it seems like there is a bug when generating a temporary
inside a foreach statement.  Here's an example.

<code>

#!/usr/bin/env rdmd

import std.stdio;
import std.conv;

struct MyFile
{
   private struct Impl
   {
      uint refs = 0;
      string name;

      this(uint r, string n)
      {
         refs = r;
         name = n;
      }
   }
   private Impl* p;

   this(string s)
   {
      writeln("MyFile ctor ", s);
      p = new Impl(1, s);
   }

   this(this)
   {
      writeln("Adding ref ", p.name);
      ++p.refs;
   }

   ~this()
   {
      writeln("MyFile dtor ", p.name);
      if(p.refs == 1) close;
      else{ writeln("Removing ref ", p.name); --p.refs;}
   }

   void close()
   {
      writeln("close ", p.name);
      scope(exit) p = null;
   }

   int opApply(int delegate(ref char) dg)
   {
      foreach(char c; p.name)
      {
         dg(c);
      }
      return 0;
   }
}

void doOne()
{
   writeln("begin one");
   auto f = MyFile("one");
   foreach(c; f)
   {
      writeln(c);
   }
   writeln("end one");
}

void doTwo()
{
   writeln("begin two");
   foreach(c; MyFile("two"))
   {
      writeln(c);
   }
   writeln("end two");
}

void main()
{
   writeln("before one");
   doOne();
   writeln("after one");
   writeln("before two");
   doTwo();
   writeln("after two");
}

</code>


The first case is handled correctly.  When the scope of doOne() ends, the f
instance is correctly destroyed.  However, in doTwo(), the temporary MyFile
created in the foreach statement is not destroyed.  In this case, "MyFile dtor
two" and "close two" should be printed before "after two".  I hit this bug
specifically when using something like  foreach(ubyte[] buf; chunks(file,
4096)).  This keeps file handles open past their lifetime and is causing a file
handle leak in my app.

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