Hello, the following program dumps core here. #include <iostream> #include <ginac/ginac.h> using namespace std; using namespace GiNaC; int main() { symbol x("x"); ex e = (ex(1)/x).numer_denom(); e = e[0]; cerr << e; } But it outputs 1 as it should if I replace the last two lines with cerr << e[0]; I don't even understand the difference! Thanks for your time, ralf
ex e = (ex(1)/x).numer_denom(); e = e[0];
Should it be allowed at all to index an ex? I believe what happens is that indexing through [] gets compiled to a call to operator*() which may not always be intended. I have encountered here another bug that was nearly untraceable with gdb but went away when I replaced e[0] with e.op(0). Just FYI, ralf
Hi! On Sat, Jul 10, 2004 at 11:50:39AM +0200, Ralf Stephan wrote:
e = e[0];
It's better to use op() here because ex::operator[] on a non-const object calls let_op() which is a more expensive operation. Anyway, it shouldn't crash (and it doesn't do that here, even with efence). A gdb backtrace would be nice. Bye, Christian -- / Physics is an algorithm \/ http://www.uni-mainz.de/~bauec002/
Anyway, it shouldn't crash (and it doesn't do that here, even with efence). A gdb backtrace would be nice.
GNU gdb 6.1.1 ... (gdb) r Starting program: /home/ralf/ginac/a.out Program received signal SIGSEGV, Segmentation fault. 0x0fdf1dcc in GiNaC::ex::print (this=0x50, c=@0x7ffff6a0, level=0) at ptr.h:92 92 T *operator->() const throw() { return p; } (gdb) bt #0 0x0fdf1dcc in GiNaC::ex::print (this=0x50, c=@0x7ffff6a0, level=0) at ptr.h:92 #1 0x0fec40cc in GiNaC::operator<< (os=@0x100132d0, e=@0x7ffff700) at operators.cpp:346 #2 0x10002188 in main () at bug3.cpp:12 ralf -- Fight those communist terrorists that try to replace a thriving commercial market (open source) with a state-supported monopoly (MS)!
I've traced it to a point where stack corruption occurs; somewhere in the printing line, operator= on the smart pointer is called, and the chaos appears while executing 'delete p' in that function: #0 __gnu_cxx::__exchange_and_add (__mem=0x100176f0, __val=-1) at atomicity.cc:55 #1 0x0ff43880 in ~symbol (this=0x10017588) at basic_string.h:215 #2 0x0ff09098 in std::_List_base<GiNaC::ex, std::allocator<GiNaC::ex> >::_M_clear (this=0x10017588) at ptr.h:78 #3 0x0ff090e0 in ~container (this=0x100177e8) at stl_list.h:328 #4 0x10002aec in GiNaC::ptr<GiNaC::basic>::operator= (this=0x40001, other=@0x11) at ptr.h:86 #5 0x1000281c in GiNaC::ex::operator= (this=0x10013238, _ctor_arg=@0x10017858) at matrix.h:107 #6 0x100021ec in main () at bug3.cpp:13 Note the func arguments in frame 4. Note also that they were intact when starting the destructor. Finally, this is not the point where the main ex is overwritten causing segv but earlier. I cannot rule out a libstdc++ bug in the (newly installed) version of g++ 3.4. Can you test that? ralf
Hi! On Thu, Jul 15, 2004 at 03:18:01PM +0200, Ralf Stephan wrote:
I cannot rule out a libstdc++ bug in the (newly installed) version of g++ 3.4. Can you test that?
I also only get this error with g++ 3.4. Anyway, given this code: ex e = lst(symbol("x"), symbol("y")); e = e[0]; the presumed sequence of events in the second line is: 1. ex::operator[]() invokes basic::operator[]() which falls back to lst::let_op() because the object is non-const. 2. lst::let_op() returns a reference to the ex which is the first element of the list. 3. ex::operator=() invokes ptr<basic>::operator=(): 3a. other.p->add_reference() adds one reference to the "x" 3b. p->remove_reference() deletes the last reference to the list 3c. delete p destroys the list, including its two ex elements and (in succession) the "y"; the "x" remains because there is still one reference to it, but this doesn't matter: the ex from the list, a reference to which was returned by let_op(), is gone. Hence, the "other" inside ptr::operator=() is now a dangling reference. 3d. p = other.p is undefined because the object referenced by "other" no longer exists. So the problem is that operator[] calls let_op(). Had it called op() like the const operator[] it would have worked (change to "e = const_cast<const ex &>(e)[0];" to verify that). Ok, so the real problem is that there is no way of selecting between the two versions of operator[] based on whether it is used as an rvalue or an lvalue. The const-ness of the target is not a strong enough prerequisite. The same problem exists with matrix::operator() (this also crashes with gcc 3.3): ex e = unit_matrix(2); e = ex_to<matrix>(e)(0, 0); Here, even the const operator() returns a reference (this should be changed!), so the const-ness of the ex_to<T> result doesn't save you. You have to wrap the result in a new ex to make it work: e = ex(ex_to<matrix>(e)(0, 0)); Suggestions for a solution? Remove the non-const operator[] and require the explicit use of let_op() to modify lists? Bye, Christian -- / Physics is an algorithm \/ http://www.uni-mainz.de/~bauec002/
Hi all, I've encountered a similar situation in my own code, i.e. the compiler chose the non-const version of an operator overload by default, even when the const version was available.
So the problem is that operator[] calls let_op(). Had it called op() like the const operator[] it would have worked (change to "e = const_cast<const ex &>(e)[0];" to verify that).
My work-around is similar, except that I might recommend: static_cast<const T&>(foo)[arg] instead of const_cast, because I wasn't discarding const-ness, but rather *enforcing* it where it was only optional, in a non-const method. This was slightly annoying to write in many places so I wrapped the operation in a less inconvenient wrapper method "const_index(const size_t) const", certainly not as compact as operator overloading, but it gets the job done without ambiguity.
Ok, so the real problem is that there is no way of selecting between the two versions of operator[] based on whether it is used as an rvalue or an lvalue. The const-ness of the target is not a strong enough prerequisite.
Hope this servers as a temporary work-around until a better solution arrives. David Fang Computer Systems Laboratory Electrical & Computer Engineering Cornell University http://www.csl.cornell.edu/~fang/ -- *gag* work in progress
participants (4)
-
Christian Bauer
-
Christian Bauer
-
David Fang
-
Ralf Stephan