Bug 4613 – temporary generated inside foreach is not correctly destructed

Status
RESOLVED
Resolution
DUPLICATE
Severity
critical
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
Mac OS X
Creation time
2010-08-10T08:54:00Z
Last change time
2010-09-22T04:05:41Z
Keywords
wrong-code
Assigned to
nobody
Creator
andy

Comments

Comment #0 by andy — 2010-08-10T08:54:33Z
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.
Comment #1 by andy — 2010-08-10T08:56:01Z
Here is the output from a test run of the example. <output> andy@curie:~/Projects/d> ./test.d before one begin one MyFile ctor one o n e end one MyFile dtor one close one after one before two begin two MyFile ctor two t w o end two after two </output>
Comment #2 by clugdbug — 2010-09-20T08:41:23Z
Probably a dup of bug 3516 -- the worst open bug in DMD.
Comment #3 by clugdbug — 2010-09-22T04:05:41Z
*** This issue has been marked as a duplicate of issue 3516 ***