mirror of
https://github.com/Z3Prover/z3
synced 2026-07-05 06:46:11 +00:00
Fix memory leaks in polymorphism instantiation engine
The polymorphism theory routed polymorphic (\) problems through theory_polymorphism, which instantiated axioms during search. Two leaks: 1. In inst::instantiate, insert_ref_map was constructed with an expr_ref argument, so its template parameter D deduced to expr_ref instead of expr*. Trail objects are region-allocated and freed without running destructors, so the embedded expr_ref never released its reference, leaking one AST subtree per instantiation. Pass e_inst.get() so D is expr*, matching the raw hashtable + manual inc_ref/dec_ref pattern. 2. trail_stack's destructor does not call reset(), so level-0 trail items (including the inc_ref balancing entries for m_from_instantiation) were never undone when the theory was destroyed. Added a ~theory_polymorphism destructor that calls m_trail.reset(). Also keeps a defensive alias check in util::unify and a fresh per-iteration substitution in inst::instantiate. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
6d5e09e2fa
commit
348bb3b6a4
3 changed files with 13 additions and 2 deletions
|
|
@ -107,13 +107,14 @@ namespace polymorphism {
|
|||
auto const& [tv, fns, substs] = m_instances[e];
|
||||
|
||||
for (auto* f2 : fns) {
|
||||
substitution sub1(m), new_sub(m);
|
||||
substitution sub1(m);
|
||||
if (!u.unify(f1, f2, sub1))
|
||||
continue;
|
||||
if (substs->contains(&sub1))
|
||||
continue;
|
||||
substitutions new_substs;
|
||||
for (auto* sub2 : *substs) {
|
||||
substitution new_sub(m);
|
||||
if (!u.unify(sub1, *sub2, new_sub))
|
||||
continue;
|
||||
if (substs->contains(&new_sub))
|
||||
|
|
@ -128,7 +129,7 @@ namespace polymorphism {
|
|||
new_substs.insert(new_sub1);
|
||||
m_from_instantiation.insert(e_inst);
|
||||
m.inc_ref(e_inst);
|
||||
t.push(insert_ref_map(m, m_from_instantiation, e_inst));
|
||||
t.push(insert_ref_map(m, m_from_instantiation, e_inst.get()));
|
||||
}
|
||||
}
|
||||
for (auto* sub2 : new_substs) {
|
||||
|
|
|
|||
|
|
@ -244,6 +244,8 @@ namespace polymorphism {
|
|||
bool util::unify(substitution const& s1, substitution const& s2,
|
||||
substitution& sub) {
|
||||
sort* v2;
|
||||
SASSERT(&s1 != &sub);
|
||||
SASSERT(&s2 != &sub);
|
||||
for (auto const& [k, v] : s1) {
|
||||
// Guard against building a cyclic substitution (e.g. A |-> list(A)),
|
||||
// which would make substitution application diverge. Such a binding
|
||||
|
|
|
|||
|
|
@ -96,6 +96,14 @@ namespace smt {
|
|||
theory(ctx, poly_family_id),
|
||||
m_inst(ctx.get_manager(), m_trail),
|
||||
m_assumption(ctx.get_manager()) {}
|
||||
|
||||
~theory_polymorphism() override {
|
||||
// Undo level-0 trail items (e.g. the inc_ref balancing entries that
|
||||
// m_inst pushes for m_from_instantiation). trail_stack's destructor
|
||||
// does not call reset(), so without this the references those items
|
||||
// hold would leak when the theory is destroyed.
|
||||
m_trail.reset();
|
||||
}
|
||||
|
||||
void init_model(model_generator & mg) override { }
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue