Skip to content

SIGSEGV in AHashMap::_lookup_pos_with_hash on deep inheritance chains containing an abstract class after commit 2fd41b7 #1862

@NathonMei

Description

@NathonMei

Godot version

master latest

godot-cpp version

master commit 2fd41b7 (2fd41b7)

System information

Manjaro Linux 25.0.8, Intel Core i5-9400F

Issue description

After commit 2fd41b7 (“Replace unordered_map with AHashMap”), a SIGSEGV caused by a null HashMapData pointer inside AHashMap::_lookup_pos_with_hash() can occur when:

  • A user-defined C++ class hierarchy contains an abstract class,
  • The inheritance chain is at least three levels deep (concrete → abstract → concrete → concrete).

Steps to reproduce

  1. Create a concrete Godot class.
class MyBaseClass : public Node3D {};
(in xx_register.cpp) GDREGISTER_CLASS(YShipActor);
  1. Derive an abstract class from it.
class AnAbstractClass : public MyBaseClass {void make_some_func = 0;};
(in xx_register.cpp) GDREGISTER_ABSTRACT_CLASS(AnAbstractClass);
  1. Derive a concrete class from the abstract one. (Still works)
class AGoodGenClass : public AnAbstractClass {};
(in xx_register.cpp) GDREGISTER_CLASS(AGoodGenClass);
  1. Add one more concrete level. (Begin having issue)
class BeginBreakClass : public AGoodGenClass {};
(in xx_register.cpp) GDREGISTER_CLASS(BeginBreakClass);
  1. Instantiate and add the last class to the scene tree.
add_child(memnew(BeginBreakClass(some_param)));

Result in stack:

Exception has occurred: Signal
signal SIGSEGV: address not mapped to object (fault address=0x0)
godot::AHashMap<godot::StringName, godot::ClassDB::ClassInfo::VirtualMethod, godot::HashMapHasherDefault, godot::HashMapComparatorDefault<godot::StringName>>::_lookup_pos_with_hash(godot::StringName const&, unsigned int&, unsigned int&, unsigned int) const (.../include/godot_cpp/templates/a_hash_map.hpp:136)
godot::AHashMap<godot::StringName, godot::ClassDB::ClassInfo::VirtualMethod, godot::HashMapHasherDefault, godot::HashMapComparatorDefault<godot::StringName>>::_lookup_pos(godot::StringName const&, unsigned int&, unsigned int&) const (.../include/godot_cpp/templates/a_hash_map.hpp:127)
godot::AHashMap<godot::StringName, godot::ClassDB::ClassInfo::VirtualMethod, godot::HashMapHasherDefault, godot::HashMapComparatorDefault<godot::StringName>>::find(godot::StringName const&) const (.../include/godot_cpp/templates/a_hash_map.hpp:579)
godot::ClassDB::get_virtual_func(void*, void const*, unsigned int) (.../src/core/class_db.cpp:300)
___lldb_unnamed_symbol82578 (@___lldb_unnamed_symbol82578:233)
___lldb_unnamed_symbol82580 (@___lldb_unnamed_symbol82580:19)
___lldb_unnamed_symbol82587 (@___lldb_unnamed_symbol82587:63)
void godot::internal::_call_native_mb_no_ret<void**, signed char*, long*>(void const*, void*, void** const&, signed char* const&, long* const&) (.../include/godot_cpp/core/engine_ptrcall.hpp:67)
godot::Node::add_child(godot::Node*, bool, godot::Node::InternalMode) (.../gen/src/classes/node.cpp:87)

Minimal reproduction project

N/A

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions