1.4: memory allocation bug with styles

What do you want to achieve?

Compile

What have you tried so far?

Compile

Screenshot or video

src/ui/ui_theme_manager.cpp: In function '_ui_local_style_t* _ui_local_style_create(const ui_style_variable_t*, bool)':
src/ui/ui_theme_manager.cpp:98:38: error: invalid conversion from 'void*' to '_ui_local_style_t*' [-fpermissive]
     _ui_local_styles = lv_mem_realloc( _ui_local_styles, (_ui_local_style_count + 1) * sizeof(_ui_local_style_t) );
                        ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/ui/ui_theme_manager.cpp: In function '_ui_local_style_property_setting_t* _ui_local_style_property_setting_create(_ui_local_style_t*, lv_obj_t*, lv_style_selector_t, lv_style_prop_t)':
src/ui/ui_theme_manager.cpp:139:65: error: invalid conversion from 'void*' to '_ui_local_style_property_setting_t*' [-fpermissive]
         local_style_p->style_property_settings = lv_mem_realloc (
                                                  ~~~~~~~~~~~~~~~^
          local_style_p->style_property_settings,
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          (local_style_p->style_property_setting_count + 1) * sizeof(_ui_local_style_property_setting_t)
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         );
         ~
*** [.pio/build/dev/src/ui/ui_theme_manager.cpp.o] Error 1e

Others

  • SquareLine Studio version: 1.4.0
  • Operating system: MacOS Sonoma
  • Target hardware: ESP32-S3

It seems the C++ compiler complains about the malloc void* casting. In C the casting from void* to the target pointer-type is not needed/advised ( c - Should I cast the result of malloc? - Stack Overflow ) and GCC C compiler didn’t even show a warning. So maybe the simplest solution for you is compiling it with a C compiler.
To compile this code with your C++ compiler the three proposed options are:

  • You can make the compiler less picky about this cast (and only show a warning instead of an error) with the -fpermissive compiler-flag argument mentioned between brackets in your compile-error message ( c++ - What does the fpermissive flag do? - Stack Overflow ), until the casting gets added to the SquareLine Studio export.
  • Making the cast in the exported code between the = and the lv_mem_realloc. In the first case in line 98 this extra code is (_ui_local_style_t*) after the =, in the second case in line 139 (_ui_local_style_property_setting_t*) is needed after the =. The export of SquareLine Studio will have to have this casting by default in the future for C++ export, because exported code shouldn’t be edited if another exports are likely to overwrite it later.
  • Exporting this code as C code and telling the C++ compiler to treat the source as C code. One usual way is using extern "C" with the #ifdef __cplusplus guard inside the C source, or without the ifdef in your C++ code, around the #include directive where you include the C source code. This one might also involve modifying the exported code after every new export, so it’s still the first option above that’s more flexible.

(LV_MEM_CUSTOM in lv_conf.h might have an impact too because it determines if standard or built-in LVGL memory allocation functions are used.)

On this topic, it would be great if squareline studio generated code that compiled with -Werror -Wall -Wextras on gcc . It’s good code hygiene and you might even find some bugs.

As for the issue, ideally the user should configure their build setup to compile .c files with a c compiler and .cc/.cxx/.cop with a c++ compiler.

1 Like

Thanks for the feedback, you’re right that every small issues should be shown at compile-time, at least as warnings (-Wall).
I think the compiler settings in the exported code/scripts still should be so that they don’t stop the compilation with error, just give warnings if there are unused variables or other minor issues like that.

One fine combination seems to be “-Wall -Wextra -Wno-unused”, as it warns about minor issues too but it doesn’t litter the output with unused variables/functions/parameters/etc. and lets the programmer decide on leaving those in the code, they don’t do much show-stopping harm after all, and maybe won’t be compiled anyway increasing the compiled binary size. ( Unfortunately -Wall/-Wextra still doesn’t give a warning about the casting from memory-allocation, the original problem of this topic, as it’s not a problem for C, just seemingly for C++. )

You want to avoid -Wno-unused because it shows you places that you don’t need the arguments or variables. Whilst you can assume the optimiser will remove them they are noise when you’re trying to maintain the system. Developers can mark those [[maybe_unused]] to mute the warnings if they have to maintain some backward compatibility. In general you want to have all warnings enabled, -Werror enabled and the developers to fix them all. The reason for this is that some warnings imply undefined behaviour which will break a system on a compiler upgrade and a change in optimiser assumptions. I’ve built everything from embedded systems to low latency trading systems, going full “no warnings” is really good for code quality.

The -Werror flag is a very useful tool before committing/releasing a code, to ensure there are no detectable compile-time problems, it’s sure, warnings can really become problems/errors sooner or later, giving undefined behaviour in compiled code, their causes should be eliminated. On the other hand, I’ve seen discussions about unused variable warnings, opinions vary wildly, but surely they can pollute the code and decrease the maintainability of libraries/etc. a bit. (And compilers sometimes have false warnings, like complaining about misfitting source-string size even if strncmp() is used to take care of that, and compilation shouldn’t stop with error due to an issue like this.)

1 Like