digitalmars.D - Heap corruption in reading struct fields in ctor
- H. S. Teoh (93/93) Dec 19 2012 While researching the causes of bug 8061, I found a very strange, and
While researching the causes of bug 8061, I found a very strange, and rather disconcerting, heap corruption bug. Please excuse the very long code; I spent several hours reducing the code already and I'm a bit tired from the effort, but I did at least find the single line that makes the difference. Also, please ignore the fact that I was experimenting with transient ranges; in the reduced code the transience doesn't even factor in (in fact, popFront isn't even in the code anymore). The bug is caused by a single line in joiner()'s nested struct's ctor. Please see embedded comments therein for details. Anyway, I need some help to further reduce this test case before I file a bug. It appears that struct members aren't being properly initialized inside the ctor? Or something else bizarre is happening here. This was tested on git HEAD, Linux/64bit. Just in case that makes a difference. ---- CODE BELOW ---- import std.array; import std.range; import std.stdio; struct TransientStringArray { dstring[] src; dchar[256] buf; this(dstring[] _src) { src = _src; } property auto front() { assert(src[0].length <= buf.length); foreach (i, ch; src[0]) { buf[i] = ch; } return buf[0 .. src[0].length]; } } auto joiner(RoR)(RoR r) { static struct Result { private: RoR _items; ElementType!RoR _current; public: this(RoR r) { _items = r; // ***** THE BUG IS HERE: ***** _current = _items.front; // This produces heap corruption //_current = r.front; // This doesn't???!!! } property auto ref front() { return _current.front; } } return Result(r); } auto makeTransientString() { auto tsa = TransientStringArray([ "ab", "cd", "ef" ]); return joiner(tsa); } void func4(T)(ref Appender!string s, T t) { writeln("func4:front = ", t.front); } void func3(T)(ref Appender!string s, T t) { writeln("front = ", t.front); func4(s, t); } string func2(R)(R src) { auto w = appender!string(); func3(w, src); return w.data; } string func1(S)(S src) { return func2(src); } void main() { // This produces a heap corruption (the output will // contain garbage characters) { auto result = makeTransientString(); func1(result); } // For some weird reason, this doesn't (or at least, it // doesn't show up) { auto result = makeTransientString(); func2(result); } } T -- Why is it that all of the instruments seeking intelligent life in the universe are pointed away from Earth? -- Michael Beibl
Dec 19 2012