Gecode / gecode

Generic Constraint Development Environment
https://www.gecode.org
Other
283 stars 76 forks source link

PropagatorGroup::kill(..) makes subsequent Space::status() to crash #56

Closed k0stjap closed 5 years ago

k0stjap commented 5 years ago

Dear Gecode developers,

it looks like If one "PropagatorGroup::kill(..)"s the only propagator in a space, the subsequent Space::status() segfault"s. In particular, The following program:

/* g++ -o bug0 =1/bug0.cpp -L/usr/local/lib -lgecodekernel -lgecodesupport -lgecodeint -lgecodesearch setenv LD_LIBRARY_PATH /usr/local/lib ./bug0

*/

include <gecode/int.hh>

include <gecode/search.hh>

using namespace Gecode;

const int iv0ds = 10;

class Sp0 : public Space { public: const char *name; IntVar iv0;

public: Sp0(const char n) : name(n), iv0(this, 0, iv0ds) {} Sp0(const char n, IntSet is) : name(n), iv0(this, is) {} Sp0(Sp0 &s) : Space(s), name(s.name) { iv0.update(*this, s.iv0); }

virtual Space copy(void) { return new Sp0(this); }

IntVar getIV0() { return (iv0); }

void print() { std::cout << name << "="; for (IntVarRanges ri(iv0); ri(); ++ri) { std::cout << ri.min() << ".." << ri.max() << " "; } std::cout << std::endl; }

void status() { switch (Space::status()) { case SS_FAILED: std::cout << "space " << name << " failed." << std::endl; break; case SS_SOLVED: std::cout << "space " << name << " is solved." << std::endl; break; case SS_BRANCH: std::cout << "space " << name << " must be branched." << std::endl; break; } } };

// int main(int argc, char* argv[]) { IntVar iv0l;

{ std::cout << std::endl << "sp = new Sp0(\"sp\", IntSet(0, 20))" << std::endl; Sp0 sp = new Sp0("sp", IntSet(0, 20)); PropagatorGroup pg; sp->print(); std::cout << "pg.size(sp) = " << pg.size(sp) << std::endl; iv0l = sp->getIV0(); BoolVar cv(sp, 0, 1); std::cout << "dom((sp)(pg), iv0l, IntSet(0, 10), cv)" << std::endl; dom((sp)(pg), iv0l, IntSet(0, 10), cv); std::cout << "pg.size(sp) = " << pg.size(sp) << std::endl; std::cout << "pg.kill(sp)" << std::endl; pg.kill(sp); std::cout << "pg.size(sp) = " << pg.size(sp) << std::endl; sp->print(); std::cout << cv << std::endl;

/ BoolVar cv2(sp, 0, 1); std::cout << "dom((sp)(pg), iv0l, IntSet(0, 10), cv2)" << std::endl; dom((sp)(pg), iv0l, IntSet(0, 10), cv2); */

std::cout << "dom(*sp, iv0l, IntSet(15, 20))"
          << std::endl;
dom(*sp, iv0l, IntSet(15, 20));
std::cout << "pg.size(*sp) = " << pg.size(*sp) << std::endl;
(void) sp->status();
std::cout << "ok??" << std::endl;
std::cout << "pg.size(*sp) = " << pg.size(*sp) << std::endl;
sp->print();
std::cout << cv << std::endl;

}

return (0); }

crashes for me with Gecode 6.1.1 (and I do not see a relevant bug fix in the 6.2.0 changelog) as follows:

kost (286) ./bug0
sp = new Sp0("sp", IntSet(0, 20)) sp=0..20 pg.size(sp) = 0 dom((sp)(pg), iv0l, IntSet(0, 10), cv) pg.size(sp) = 1 pg.kill(sp) pg.size(sp) = 0 sp=0..20 [0..1] dom(sp, iv0l, IntSet(15, 20)) pg.size(*sp) = 0 Segmentation fault (core dumped)

.. however, if one enables the commented out code near the end of the program - with another 'dom()' progagator post, the program runs fine:

kost (284) ./bug0
sp = new Sp0("sp", IntSet(0, 20)) sp=0..20 pg.size(sp) = 0 dom((sp)(pg), iv0l, IntSet(0, 10), cv) pg.size(sp) = 1 pg.kill(sp) pg.size(sp) = 0 sp=0..20 [0..1] dom((sp)(pg), iv0l, IntSet(0, 10), cv2) dom(sp, iv0l, IntSet(15, 20)) pg.size(sp) = 1 space sp is solved. ok?? pg.size(*sp) = 0 sp=15..20 [0..1]

Did I miss something??

Cheers,

--- Kostja.

chschulte commented 5 years ago

Yes, that looks like a genuine bug but I still have to figure out a good fix (Basically iterating over a data structure while deleting from it, typically a bad idea...).

Thanks for the detailed report!

chschulte commented 5 years ago

I had another look. The bug only occurs when the last propagator in a space is deleted which is also not stable. Hence when you add sp->status() just before the kill, things work as expected.

Hence the obvious fix would say that kills can only be performed on stable spaces.

Would that be to restrictive?

k0stjap commented 5 years ago

.. thanks, I see your point - and I believe I can live with the restriction!

Cheers,

--- Kostja.

chschulte commented 5 years ago

I now have reconstructed the invariant that is violated. It is easy to fix but I am short on time, right now.

chschulte commented 5 years ago

Fixed in develop.

k0stjap commented 5 years ago

thanks!