Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash using Ref as parameter #1024

Closed
zhehangd opened this issue Jan 30, 2023 · 2 comments · Fixed by #1045
Closed

Crash using Ref as parameter #1024

zhehangd opened this issue Jan 30, 2023 · 2 comments · Fixed by #1045
Labels
bug This has been identified as a bug crash

Comments

@zhehangd
Copy link
Contributor

zhehangd commented Jan 30, 2023

System: Kubuntu 20.04, Godot Beta 16, godot-cpp: 0f3a091

A function like this crashes immediately when it is called with a non-null custom object as parameter.

String test_foo(Ref<Foo> foo) const
struct Foo : public RefCounted {
  GDCLASS(Foo, RefCounted)
  static void _bind_methods() {}
};

struct FooUser : public RefCounted {
  GDCLASS(FooUser, RefCounted)
  
  String test_foo(Ref<Foo> foo) const {
    return foo.is_valid() ? String{"foo"} : String{"no foo"};
  }
  
  String test_image(Ref<Image> image) const {
    return image.is_valid() ? String{"image"} : String{"no image"};
  }

  Ref<Foo> create_foo(void) const { return {memnew(Foo)}; }
  
  static void _bind_methods() {
    ClassDB::bind_method(D_METHOD("test_foo"), &FooUser::test_foo);
    ClassDB::bind_method(D_METHOD("test_image"), &FooUser::test_image);
    ClassDB::bind_method(D_METHOD("create_foo"), &FooUser::create_foo);
  }
};

I saw #1021 so in addition to the custom Foo class I also tested with Image.
For Foo I tried instantiating directly from GDSCript (2) and from a GDExtension function (3).

var foo_user := FooUser.new()
var foo1 := Foo.new()
var foo2 := foo_user.create_foo()

printerr("1 ", foo_user.test_foo(null)) # ok
#printerr("2 ", foo_user.test_foo(foo1)) # crash
#printerr("3 ", foo_user.test_foo(foo2)) # crash

var img1 = Image.new()
printerr("4 ", foo_user.test_image(null)) # ok
printerr("5 ", foo_user.test_image(img1)) # ok
#printerr("6 ", foo_user.test_image(Image.new())) # std::system_error Invalid argument

Either case, passing a Foo object crashed the application

handle_crash: Program crashed with signal 11
Engine version: Godot Engine v4.0.beta16.official (518b9e5801a19229805fe837d7d0cf92920ad413)
Dumping the backtrace. Please include this when reporting the bug to the project developer.
[1] /lib/x86_64-linux-gnu/libc.so.6(+0x43090) [0x7fec32b87090] (??:0)
[2] /lib/x86_64-linux-gnu/libpthread.so.0(+0xae27) [0x7fec32e95e27] (??:0)
[3] /home/zhehangd/Main/projects/Dust/dust_buildspace/Godot_v4.0-beta16_linux.x86_64() [0x44b3b2a] (??:0)
[4] void godot::call_with_ptr_args_retc_helper<godot::___UnexistingClass, godot::String, godot::Ref<Foo>, 0ul>(godot::___UnexistingClass*, godot::String (godot::___UnexistingClass::*)(godot::Ref<Foo>) const, void const* const*, void*, IndexSequence<0ul>) (??:0)
[5] void godot::call_with_ptr_args<godot::___UnexistingClass, godot::String, godot::Ref<Foo> >(godot::___UnexistingClass*, godot::String (godot::___UnexistingClass::*)(godot::Ref<Foo>) const, void const* const*, void*) (??:0)
[6] godot::MethodBindTRC<godot::String, godot::Ref<Foo> >::ptrcall(void*, void const* const*, void*) const (??:0)
...

For Image, it seems ok by giving it a variable (5), but an exception is thrown if I new inside the statement (6).
I don't know if it is another issue or a known limitation.

terminate called after throwing an instance of 'std::system_error'
  what():  Invalid argument

Inserting print-to-cerr code indicates that the crashes happen before any code inside the function is executed.

[5] void godot::call_with_ptr_args<godot::___UnexistingClass, godot::String, godot::Ref<Foo> >(godot::___UnexistingClass*, godot::String (godot::___UnexistingClass::*)(godot::Ref<Foo>) const, void const* const*, void*) (??:0)

The "__UnexistingClass" text looks suspicious.
In my real project there wasn't this text in the backtrace.

handle_crash: Program crashed with signal 11
Engine version: Godot Engine v4.0.beta16.official (518b9e5801a19229805fe837d7d0cf92920ad413)
Dumping the backtrace. Please include this when reporting the bug to the project developer.
[1] /lib/x86_64-linux-gnu/libc.so.6(+0x43090) [0x7f7aa7140090] (??:0)
[2] /lib/x86_64-linux-gnu/libpthread.so.0(+0xae27) [0x7f7aa744ee27] (??:0)
[3] /home/zhehangd/Main/projects/Dust/dust_buildspace/Godot_v4.0-beta16_linux.x86_64() [0x44b3b2a] (??:0)
[4] godot::MethodBindT<godot::Ref<dust::godot_::DustWorld> >::ptrcall(void*, void const* const*, void*) const (??:0)

@hakuhan
Copy link

hakuhan commented Feb 15, 2023

I also got this issue. When I tried pass Object* as parameter. Engin will crash.

@zhehangd
Copy link
Contributor Author

zhehangd commented Feb 15, 2023

Narrowed the crash down to

T *obj = reinterpret_cast<T *>(godot::internal::gde_interface->object_get_instance_binding(godot::internal::gde_interface->ref_get_object(ref), godot::internal::token, &T::___binding_callbacks));

Hard to tell, but #958 might be related.

Inserting the following snippet before this line prints the instance ID. It turns out that the printed ID (72759616) isn't the same as the true object ID (-9223372010497769052). It indicates that at least obj_ptr has already broken. Not sure about ref as I don't know how to verify.

GDExtensionObjectPtr obj_ptr = godot::internal::gde_interface->ref_get_object(ref);
std::int64_t id = godot::internal::gde_interface->object_get_instance_id(obj_ptr);
WARN_PRINT(godot::String::num_int64(id));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This has been identified as a bug crash
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants