0 votes

Hi.
I'm trying to read (and modify) InputMap from C++ via GDNative.
I could write a code to access InputMap, but it makes the engine crash on exit.
The root cause seems something related to reference counting. Any advise please?

Platform: Windows 64bit
Version: 3.1.1.stable.official, 3.2.dev.custom_build.d2f38dbb2

A following code fragment is a core part of my code.

void godot::MyNode::_init()
{
  godot::Array al = godot::InputMap::get_singleton()->get_actions();
  for (int idx = 0; idx < al.size(); ++idx) {
    const godot::Array events= godot::InputMap::get_singleton()->get_action_list(al[idx]);
    for (int ei = 0; ei < events.size(); ei++) {
      const Ref<InputEvent> ev = events[ei];
      //const InputEvent *ev = events[ei];

Referencing 'events[ei]' with Ref or raw pointer causes the crash with a following message.

ERROR: ScriptServer::get_language: Index p_idx=0 out of size (_language_count=0)
   At: core\script_language.cpp:84

Simplified stack trace:

godot.windows.tools.64.exe!Reference::unreference() Line 97 C++
godot.windows.tools.64.exe!Ref<Reference>::unref() Line 280 C++
godot.windows.tools.64.exe!RefPtr::unref() Line 83  C++
godot.windows.tools.64.exe!Variant::clear() Line 1111   C++
godot.windows.tools.64.exe!Variant::~Variant() Line 422 C++

godot.windows.tools.64.exe!CowData<Variant>::~CowData<Variant>() Line 369   C++
godot.windows.tools.64.exe!Vector<Variant>::~Vector<Variant>() Line 126 C++

godot.windows.tools.64.exe!Array::~Array() Line 421 C++

godot.windows.tools.64.exe!Variant::~Variant() Line 422 C++

godot.windows.tools.64.exe!List<Pair<Variant const *,Variant>,DefaultAllocator>::~List<Pair<Variant const *,Variant>,DefaultAllocator>() Line 711   C++

godot.windows.tools.64.exe!Dictionary::~Dictionary() Line 289   C++

godot.windows.tools.64.exe!Variant::~Variant() Line 422 C++

godot.windows.tools.64.exe!memdelete_allocator<Map<StringName,ProjectSettings::VariantContainer,Comparator<StringName>,DefaultAllocator>::Element,DefaultAllocator>(Map<StringName,ProjectSettings::VariantContainer,Comparator<StringName>,DefaultAllocator>::Element * p_class) Line 133  C++

godot.windows.tools.64.exe!Map<StringName,ProjectSettings::VariantContainer,Comparator<StringName>,DefaultAllocator>::~Map<StringName,ProjectSettings::VariantContainer,Comparator<StringName>,DefaultAllocator>() Line 684 C++
godot.windows.tools.64.exe!ProjectSettings::~ProjectSettings() Line 1212    C++
godot.windows.tools.64.exe!Main::cleanup() Line 2094    C++

The code around Reference::unreference():97:

    if (instance_binding_count > 0) {
        for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) {
            if (_script_instance_bindings[i]) {
                bool script_ret = ScriptServer::get_language(i)->refcount_decremented_instance_binding(this);
                die = die && script_ret;
            }
        }
    }

'instancebindingcount' was 1. Since ScriptServer::finishlanguages() was called before Main::cleanup():2094 (at Main::cleanup():2055), I think 'instancebinding_count' should not be non-zero at this point.
But I could not find how this condition can be achieved.

asked Oct 22, 2019 in Engine by yosagi (12 points)

I've copy-pasted the wrong stack trace on my post. The stack trace I showed was not a result from the code alone. It was produced with the code and a cleanup code below:

extern "C" void GDN_EXPORT godot_gdnative_terminate(godot_gdnative_terminate_options *o)
{
  godot::Array al=godot::InputMap::get_singleton()->get_actions();
  for (int idx = 0; idx < al.size(); ++idx) {
    godot::InputMap::get_singleton()->erase_action(al[idx]);
  }
  godot::Godot::gdnative_terminate(o);
}

Without this cleanup code, the engine crashes at earlier stage with the similar reason.

    godot.windows.tools.64.exe!Reference::unreference() Line 97 C++
    godot.windows.tools.64.exe!Ref<InputEvent>::unref() Line 280    C++
    godot.windows.tools.64.exe!Ref<InputEvent>::~Ref<InputEvent>() Line 298 C++
    [External Code] 
    godot.windows.tools.64.exe!memdelete_allocator<List<Ref<InputEvent>,DefaultAllocator>::Element,DefaultAllocator>(List<Ref<InputEvent>,DefaultAllocator>::Element * p_class) Line 133    C++
    godot.windows.tools.64.exe!List<Ref<InputEvent>,DefaultAllocator>::_Data::erase(const List<Ref<InputEvent>,DefaultAllocator>::Element * p_I) Line 174   C++
    godot.windows.tools.64.exe!List<Ref<InputEvent>,DefaultAllocator>::erase(const List<Ref<InputEvent>,DefaultAllocator>::Element * p_I) Line 368  C++
    godot.windows.tools.64.exe!List<Ref<InputEvent>,DefaultAllocator>::clear() Line 405 C++
    godot.windows.tools.64.exe!List<Ref<InputEvent>,DefaultAllocator>::~List<Ref<InputEvent>,DefaultAllocator>() Line 711   C++
    [External Code] 
    godot.windows.tools.64.exe!memdelete_allocator<Map<StringName,InputMap::Action,Comparator<StringName>,DefaultAllocator>::Element,DefaultAllocator>(Map<StringName,InputMap::Action,Comparator<StringName>,DefaultAllocator>::Element * p_class) Line 133    C++
    godot.windows.tools.64.exe!Map<StringName,InputMap::Action,Comparator<StringName>,DefaultAllocator>::_cleanup_tree(Map<StringName,InputMap::Action,Comparator<StringName>,DefaultAllocator>::Element * p_element) Line 509  C++
    godot.windows.tools.64.exe!Map<StringName,InputMap::Action,Comparator<StringName>,DefaultAllocator>::_cleanup_tree(Map<StringName,InputMap::Action,Comparator<StringName>,DefaultAllocator>::Element * p_element) Line 507  C++
    godot.windows.tools.64.exe!Map<StringName,InputMap::Action,Comparator<StringName>,DefaultAllocator>::_cleanup_tree(Map<StringName,InputMap::Action,Comparator<StringName>,DefaultAllocator>::Element * p_element) Line 507  C++
    godot.windows.tools.64.exe!Map<StringName,InputMap::Action,Comparator<StringName>,DefaultAllocator>::clear() Line 664   C++
    godot.windows.tools.64.exe!Map<StringName,InputMap::Action,Comparator<StringName>,DefaultAllocator>::~Map<StringName,InputMap::Action,Comparator<StringName>,DefaultAllocator>() Line 684   C++
    [External Code] 
    godot.windows.tools.64.exe!memdelete<InputMap>(InputMap * p_class) Line 122 C++
    godot.windows.tools.64.exe!Main::cleanup() Line 2090    C++
    godot.windows.tools.64.exe!widechar_main(int argc, wchar_t * * argv) Line 153   C++
    godot.windows.tools.64.exe!_main() Line 173 C++
    godot.windows.tools.64.exe!main(int _argc, char * * _argv) Line 185 C++

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.