www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Heap corruption in reading struct fields in ctor

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

---- 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
		RoR _items;
		ElementType!RoR _current;
		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();

		// For some weird reason, this doesn't (or at least, it
		// doesn't show up)
			auto result = makeTransientString();


Why is it that all of the instruments seeking intelligent life in the
universe are pointed away from Earth? -- Michael Beibl
Dec 19 2012