Heap corruption in reading struct fields in ctor
H. S. Teoh
hsteoh at quickfur.ath.cx
Wed Dec 19 18:21:14 PST 2012
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
More information about the Digitalmars-d
mailing list