mitsuba-renderer / nanogui

Minimalistic C++/Python GUI library for OpenGL, GLES2/3, Metal, and WebAssembly/WebGL
Other
1.57k stars 196 forks source link

ASAN reporting undefined behaviour due to bad casting #36

Open opeik opened 4 years ago

opeik commented 4 years ago

Howdy, I've added nanogui to my existing OpenGL 4.1 project. When I run my project in debug mode ASAN reports the following:

/usr/local/opt/llvm/include/c++/v1/functional:1875:23: runtime error: member call on address 0x615000065860 which does not point to an object of type 'std::__1::__function::__base<void (const nanogui::Color &)>'
0x615000065860: note: object is of type 'std::__1::__function::__func<nanogui::ColorPicker::ColorPicker(nanogui::Widget*, nanogui::Color const&)::$_0, std::__1::allocator<nanogui::ColorPicker::ColorPicker(nanogui::Widget*, nanogui::Color const&)::$_0>, void (nanogui::Color const&)>'
 be be be be  30 8b 7d 0b 01 00 00 00  be be be be be be be be  be be be be be be be be  be be be be
              ^~~~~~~~~~~~~~~~~~~~~~~
              vptr for 'std::__1::__function::__func<nanogui::ColorPicker::ColorPicker(nanogui::Widget*, nanogui::Color const&)::$_0, std::__1::allocator<nanogui::ColorPicker::ColorPicker(nanogui::Widget*, nanogui::Color const&)::$_0>, void (nanogui::Color const&)>'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/local/opt/llvm/include/c++/v1/functional:1875:23 in 
/usr/local/opt/llvm/include/c++/v1/functional:1876:23: runtime error: member call on address 0x615000065860 which does not point to an object of type 'std::__1::__function::__base<void (const nanogui::Color &)>'
0x615000065860: note: object is of type 'std::__1::__function::__func<nanogui::ColorPicker::ColorPicker(nanogui::Widget*, nanogui::Color const&)::$_0, std::__1::allocator<nanogui::ColorPicker::ColorPicker(nanogui::Widget*, nanogui::Color const&)::$_0>, void (nanogui::Color const&)>'
 be be be be  30 8b 7d 0b 01 00 00 00  be be be be be be be be  be be be be be be be be  be be be be
              ^~~~~~~~~~~~~~~~~~~~~~~
              vptr for 'std::__1::__function::__func<nanogui::ColorPicker::ColorPicker(nanogui::Widget*, nanogui::Color const&)::$_0, std::__1::allocator<nanogui::ColorPicker::ColorPicker(nanogui::Widget*, nanogui::Color const&)::$_0>, void (nanogui::Color const&)>'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/local/opt/llvm/include/c++/v1/functional:1876:23 in 
/usr/local/opt/llvm/include/c++/v1/functional:1819:19: runtime error: member call on address 0x7ffee8a4bc20 which does not point to an object of type 'std::__1::__function::__base<void (const nanogui::Color &)>'
0x7ffee8a4bc20: note: object is of type 'std::__1::__function::__func<nanogui::ColorPicker::ColorPicker(nanogui::Widget*, nanogui::Color const&)::$_0, std::__1::allocator<nanogui::ColorPicker::ColorPicker(nanogui::Widget*, nanogui::Color const&)::$_0>, void (nanogui::Color const&)>'
 50 61 00 00  30 8b 7d 0b 01 00 00 00  6c d4 a1 07 01 00 00 00  00 00 00 00 00 00 80 3f  00 00 00 00
              ^~~~~~~~~~~~~~~~~~~~~~~
              vptr for 'std::__1::__function::__func<nanogui::ColorPicker::ColorPicker(nanogui::Widget*, nanogui::Color const&)::$_0, std::__1::allocator<nanogui::ColorPicker::ColorPicker(nanogui::Widget*, nanogui::Color const&)::$_0>, void (nanogui::Color const&)>'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/local/opt/llvm/include/c++/v1/functional:1819:19 in 

lldb output

Process 6823 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = Dynamic type mismatch
// There's a bunch of STL code here, I ignored it for brevity
frame #7: 0x000000010047d87d afk`nanogui::ColorPicker::set_callback(this=0x0000615000055800, callback= Function = Afk::Engine::get()::instance )> const&) at colorpicker.h:46:20
   43        * \ref nanogui::ColorPicker::mPickButton.
   44        */
   45       void set_callback(const std::function<void(const Color &)> &callback) {
-> 46           m_callback = callback;
   47           m_callback(background_color());
   48       }
   49   
(lldb) 
frame #8: 0x000000010047af29 afk`nanogui::detail::FormWidget<nanogui::Color, std::__1::integral_constant<bool, true> >* nanogui::FormHelper::add_variable<nanogui::Color>(this=0x000060c000075ac0, label="Color", setter= Function = Afk::Engine::get()::instance , getter= Function = Afk::Engine::get()::instance , editable=true)> const&, std::__1::function<nanogui::Color ()> const&, bool) at formhelper.h:166:17
   163                  widget->set_value(value);
   164          };
   165          refresh();
-> 166          widget->set_callback(setter);
   167          widget->set_editable(editable);
   168          widget->set_font_size(m_widget_font_size);
   169          Vector2i fs = widget->fixed_size();
(lldb) 
frame #9: 0x000000010030399b afk`nanogui::detail::FormWidget<nanogui::Color, std::__1::integral_constant<bool, true> >* nanogui::FormHelper::add_variable<nanogui::Color>(this=0x000060c000075ac0, label="Color", value=0x000000010086b46c, editable=true) at formhelper.h:184:16
   181      /// Add a new data widget that exposes a raw variable in memory
   182      template <typename Type> detail::FormWidget<Type> *
   183      add_variable(const std::string &label, Type &value, bool editable = true) {
-> 184          return add_variable<Type>(label,
   185              [&](const Type & v) { value = v; },
   186              [&]() -> Type { return value; },
   187              editable
(lldb) 
frame #10: 0x00000001002fd6d1 afk`Afk::DebugMenu::setup_forms(this=0x000000010086b2a0) at DebugMenu.cpp:42:14
   39   
   40     this->gui->add_group("Complex types");
   41     this->gui->add_variable("Enumeration", this->enumval, true)->set_items({"Item 1", "Item 2", "Item 3"});
-> 42     this->gui->add_variable("Color", this->colval);
   43   
   44     this->gui->add_group("Other widgets");
   45     this->gui

DebugMenu.hpp

class DebugMenu : public nanogui::Screen {
public:
  DebugMenu(Renderer::Window _window);

private:
  nanogui::FormHelper *gui             = {};
  nanogui::ref<nanogui::Window> window = {};

  enum test_enum { Item1 = 0, Item2, Item3 };

  bool bvar             = true;
  int ivar              = 12345678;
  double dvar           = 3.1415926;
  float fvar            = 3.1415926f;
  std::string strval    = "A string";
  test_enum enumval     = Item2;
  nanogui::Color colval = nanogui::Color{0.5f, 0.5f, 0.7f, 1.f};
};

DebugMenu.cpp

DebugMenu::DebugMenu(Renderer::Window _window) {
  this->initialize(_window.get(), false);

  this->gui = new nanogui::FormHelper{this};
  this->window = this->gui->add_window(Vector2i{10, 10}, "Form helper example");

  this->gui->add_group("Basic types");
  this->gui->add_variable("bool", this->bvar)->set_tooltip("Test tooltip.");
  this->gui->add_variable("string", this->strval);

  this->gui->add_group("Validating fields");
  this->gui->add_variable("int", this->ivar)->set_spinnable(true);
  this->gui->add_variable("float", this->fvar)->set_tooltip("Test.");
  this->gui->add_variable("double", this->dvar)->set_spinnable(true);

  this->gui->add_group("Complex types");
  this->gui->add_variable("Enumeration", this->enumval, true)->set_items({"Item 1", "Item 2", "Item 3"});
  this->gui->add_variable("Color", this->colval);

  this->gui->add_group("Other widgets");
  this->gui
      ->add_button("A button", []() { Afk::status << "Button pressed.\n"; })
      ->set_tooltip("Testing a much longer tooltip, that will wrap around to "
                    "new lines multiple times.");

  this->perform_layout();
  this->window->center();
  this->set_visible(true);
}

Render loop

  this->renderer.clear_screen(); // calls glClear
  // Draw code here
  this->debug_menu.draw_widgets();
  this->renderer.swap_buffers(); // calls glfwSwapBuffers

Other details OS: macOS 10.15.3 Compiler: clang version 9.0.1 via brew

opeik commented 4 years ago

Using a custom getter/setter still causes the issue.