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