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

Reply via email to