On Thu, 11 Nov 2010 14:50:10 -0500, spir <[email protected]> wrote:
Thank you very much for your help, Steve. I think now the bug is not in
my code. An evidence is I never play with memory: every element is a
class instance (many should later become structs or even simpler
thingies, but I first chose this design for simplicity); there is no
malloc or such, not even a single pointer; and indeed, I do not
deallocate anything manually, and assign nothing to null. So, how come a
segfault? See also below.
You're welcome, and there are other ways to have issues with pointers.
The most common is not deleting something from the heap, but rather
returning stack memory from a function.
Try this: inside the constructor do:
writeln(this.pattern);
writeln(this);
writeln(this.pattern);
Runs fine, see also below. I'm sure now that:
* the pattern is ok as long as we remain inside this()
* the pattern is corrupted as soon as we quit this()
(Actually, its contents are corrupted, precisely its field 'pattern', an
array that holds its subpatterns.)
This really sounds like an issue where stack data is being returned.
[...]
If not, then it's
something being printed in your List class. I don't have the code that
converts your Pattern class to a string, etc. so I can't say whether
they
are an issue.
I printed it in last post (but was at the end). It's just a call to a
tool func listText that wrap join()Here it is again:
class Tuple : Pattern {
// ........
override string toString () {
/** "(p1 p2 ...)" */
return listText!Pattern(this.patterns, " " ,"(",")");
}
}
string listText(Element) (Element[] elements,
string sep, string lDelim,string rDelim) {
/** textual representation of elements held in a plain array */
string[] elementTexts = new string[elements.length];
foreach (uint i, Element element ; elements)
elementTexts[i] = to!string(element);
string content = join(elementTexts, sep);
return format("%s%s%s", lDelim, content, rDelim);
}
It's the to!string(element) that I don't have the code to -- each object's
toString function. But I'm no longer worried about that. If it works
properly inside the ctor, it should work properly outside.
If those three lines work in the constructor, I'd say there is a
possible
compiler error, because there is no difference between calling that code
from in the constructor or in the test code.
I agree with your reasoning. (But would not dare concluding there is a
bug in dmd :-)
It's not unheard of :) But I still would rule out all other possibilities
before concluding that. I've had very strange dmd bugs where things only
fail when certain ordering of structures or code affects them. It does
happen.
If that's the case, create a function that prints out all the addresses
of
things (you can print out the address of a class by simply casting the
class reference to a void *). Print that out between each line and see
what changes, then focus there. Again, without more code, I can't say
for
certain what's going on.
Here it is: I added some debug code to the constructor and the test
func. Below code and output. The segfault happens here on call to match.
I added not only the address of the pattern, but also of its .patterns
field, and of its 2 sub-patterns.
============== List.this ======================
this (Pattern element, Pattern sep, uint min=2) {
this.min = min;
// for output
this.element = element;
this.sep = sep;
// Construct pattern.
this.pattern = new Tuple(
element,
new ZeroOrMore(new Tuple(sep,element))
);
// checking
writeln("--- in List.this ---");
writeln(this.pattern);
writeln(this);
writeln(this.pattern);
writeln(cast(void*)(this));
writeln(cast(void*)(this.pattern));
writeln(cast(void*)(this.pattern.patterns)); // array
writeln(cast(void*)(this.pattern.patterns[0]));
writeln(cast(void*)(this.pattern.patterns[1]));
}
============== testList2 ======================
void testList2 () {
writeln("=== List ========================");
auto number = new String(new Klass("0-9"));
auto PLUS = new Literal("+");
auto addition = new List(number, PLUS);
writeln("--- in testList2 ---");
writeln(addition);
writeln(cast(void*)(addition));
writeln(cast(void*)(addition.pattern));
writeln(cast(void*)(addition.pattern.patterns)); // array
writeln(cast(void*)(addition.pattern.patterns[0]));
writeln(cast(void*)(addition.pattern.patterns[1]));
// use
auto node = addition.match("1+23+456");
assert (node.toString() == `["1" "23" "456"]`);
}
============== output ======================
--- in List.this ---
([0-9]+ ("+" [0-9]+)*)
List([0-9]+, "+", 2)
([0-9]+ ("+" [0-9]+)*)
46DF40
46ECA0
BFA107E0
46ECE0
46EC80
--- in testList2 ---
List([0-9]+, "+", 2)
46DF40
46ECA0
BFA107E0
BFA1070A
38C4E0
Segmentation fault
As you see, the addresses of the 2 sub-patterns have changed (but the
array that holds them hasn't moved -- and I just checked that
cast(void*)array actually returns the ptr). Don't know what to conclude.
OK, can we see the code for Tuple? That may be where something fishy is
occurring.
-Steve