variable's address changing when for loop entered ...

Mark Johnson mj1@lx.cog.brown.edu
Tue Mar 24 15:56:00 GMT 1998


All,

Thanks for making wonderful tools like the new egcs compilers freely
available!  I don't mean to be critical, but I think I may have come
across a bug in egcs c++.  The address of a const variable changes
when I enter a for loop, resulting in a segmentation fault, even
though I can see no apparent reason for this to happen.

I am using the following version of egcs c++

mj on lugha [25] % c++ -v
Reading specs from /usr/local/lib/gcc-lib/i586-pc-linux-gnulibc1/egcs-2.90.23/specs
gcc version egcs-2.90.23 980102 (egcs-1.0.1 release)

(Actually I just downloaded and tried the egcs-1.0.2 release; the bug
still occurs.  I did a standard install, but requested
--enable-shared.  I think I also have an old version of binutils, as
my compiler seems to fail all the exception-handling tests).

Anyway, the problem only arises deep into my natural language parsing
application; the same code is executed nonproblematically many
hundreds of thousands of times before the problem shows up.  I have
isolated the problem to a specific line in the code, but I have
no idea how to isolate the bug more specifically; sorry.

The function in which the error shows up is in unary_inside.  The
relevant code before I inserted my debugging code is the following.

typedef size_t Bindex;     // index into vector of weighted binary trees

// ...

void
unary_inside(const Grammar& g, Chart& c, ChartCell& cc, Bindex child_bi)
{
  const Btree& child_bt = c.btree(child_bi);        // fetch Btree
  const RuleIdList& urs=g.urules[child_bt.label];   // look up rules for child label
  for (RuleIdList::const_iterator rii=urs.begin(); rii!=urs.end(); rii++) { // try each rule
    Bindex bi = add_inside(c, cc, g.weight(*rii)*child_bt.weight, g.rule_parent(*rii), child_bi, 0);
    if (bi)                         // did we build a new tree?
      unary_inside(g, c, cc, bi);   //  yes.  try to extend it
  }
}

While the for loop in unary_inside is executed hundreds of thousands
of times without a problem, at a certain stage in parsing the value of
&urs and &child_bt seems to change when we enter the for loop.  Then
urs.begin() gets set to an incorrect value (specifically,
urs.begin()!=urs.end(), whereas I know that in this circumstance
urs.begin()==urs.end()), and all hell breaks loose (the program seg
faults shortly thereafter).

I discovered this by inserting the debugging code below.  The flag
debug_flag is set by the parser when it starts working on the substring
spanning words 21 to 25 in the input string.  Point 1a is just before
entering the for loop; point 2 is the first statement inside the for
loop.  Note that the addresses &urs and &child_bt change when the
loop is entered for no apparent reason.

...
unary_inside: child_bi = 8193 ROOT (0)
 point 1, &urs = 0x807b4f0, &child_bt = 0x4016e008, child_bt.weight = 5.22046e-14
 point 1a, urs.begin()!=urs.end() = 0, &urs = 0x807b4f0
 point 2, &urs = 0x807b4f4, &rii = 0xbffff4ec, &child_bt = 0x40144f40

void
unary_inside(const Grammar& g, Chart& c, ChartCell& cc, Bindex child_bi)
{
  if (debug_flag) cerr<<"unary_inside: child_bi = "<<child_bi<<' '<<id_string(c.btree(child_bi).label)<<" ("<<c.btree(child_bi).label<<")\n";
  const Btree& child_bt = c.btree(child_bi);
  assert(child_bt.label<g.urules.size());
  const RuleIdList& urs=g.urules[child_bt.label];
  if (debug_flag) cerr<<" point 1, &urs = "<<&urs<<", &child_bt = "<<&child_bt<<", child_bt.weight = "<<child_bt.weight<<"\n";
  if (debug_flag) cerr<<" point 1a, urs.begin()!=urs.end() = "<<(urs.begin()!=urs.end());
  if (debug_flag) cerr<<", &urs = "<<&urs<<'\n';
  for (RuleIdList::const_iterator rii=urs.begin(); rii!=urs.end(); rii++) {
    if (debug_flag) cerr<<" point 2, &urs = "<<&urs<<", &rii = "<<&rii<<", &child_bt = "<<&child_bt<<"\n";
    assert(*rii<g.nrules()); assert(g.rule(*rii)[0]==g.rule_parent(*rii)); 
    assert(g.weight(*rii)*child_bt.weight>0.0); 
    Bindex bi = add_inside(c, cc, g.weight(*rii)*child_bt.weight, g.rule_parent(*rii), child_bi, 0);
    if (bi)
      unary_inside(g, c, cc, bi);
  }
}

The file ftp://lx.cog.brown.edu/pub/mj/egcs-problem.tgz contains this
file, all source and data files, and a Makefile such that `make bug'
will build and run the program which demonstrated the bug.

Any suggestions or advice?

Thanks

Mark Johnson
Mark_Johnson@brown.edu
22nd March 1998



More information about the Gcc-bugs mailing list