FreeRTOS and c++ rtti

Hello,

I try to embed c++ code into the freertos-based firmware of the crazyflie drone, with an arm embedded gcc.

I succeeded in compiling, linking, launching, but dynamic_cast<> always returns nullptr, and exceptions raised are not caught. I enabled flags such as -fexceptions, -rtti, to no avail. Something to know: it’s freertos that launches a task that eventually calls a c++ function which in turn does c++ stuff.

Has anyone succeeded in doing this? I searched on numerous forums, including this one, but couldn’t find any information.

(and I’m aware rtti and exception are not recommended in embedded apps, but I still want to try)

Best,
Stéphane

I have used dynamic_cast in a FreeRTOS based C++ application and it works fine. My first guess is that your problem is totally unrelated to FreeRTOS, as you can’t derive from its structs to use RTTI anyway.

My thoughts on possible sources, make sure your main is i a .cpp file, and that you are linking the project as a C++ project. Also make sure the classes you are trying to use dynamic_cast on have virtual functions (at minimum a virtual destructor).

I would say that there isn’t that much of an issue with RTTI in embedded, it will space in the flash for the type tables, but doesn’t really impact execution when you are not using it. Exceptions may be a bit problematic, you need to make sure the exception handling is thread safe, and that all tasks that might leak an exception are wrapped in a catch all clause.

Thank you Richard.
Since FreeRTOS requires to redefine operator new and delete, I was thinking that maybe I was overlooking something.

Yes, c++ files are compiled and linked with a c++ compiler, and the classes are suitable, the small test I did perfectly works on my mac.

FreeRTOS does NOT redefine new and delete, but provides a thread safe version of memory allocation. If you are using new, then you need to make sure that the underlying library malloc(), free() and family have been made thread safe, often it isn’t good enough to just make new and delete safe, because other parts of the library may still be using malloc and free.

You likely used a different implementation to run on your Mac, (it may still be gcc, but it could have different options bundled in), you should check the options that your embedded gcc is using to make sure that RTTI is enabled, and the linker file that that information is actually being linked in.

Yes that’s what I wrote, “FreeRTOS requires” that op new and delete be redefined.

Thank you for your suggestions to look at the symbol. I just checked libsupc++.a with objdump and here is the result for dynamic_cast:

00000000 g F .text.__dynamic_cast 00000138 __dynamic_cast

The fact that its number is 000… is not a good sign (even though its alignement or size is 138?!)

No, using FreeRTOS you don’t want to try to fix new and delete, but you want to fix malloc and free, which new/delete are almost certain to call. as fixing new/delete isn’t enough, as parts of the library will be using malloc/free, and fixing that will very likely fix new/delete.

The 0000000 in the lib dump isn’t necessarily bad, as I think that is saying the the dynamic cast function is at relative 0 to the segment .text.__dynamic_cast (i.e the beginning of the segment), you will likely find many functions with a 0 offset like that.


richard-damon

    March 30

No, using FreeRTOS you don’t want to try to fix new and delete, but you want to fix malloc and free, which new/delete are almost certain to call. as fixing new/delete isn’t enough, as parts of the library will be using malloc/free, and fixing that will very likely fix new/delete.

The 0000000 in the lib dump isn’t necessarily bad, as I think that is saying the the dynamic cast function is at relative 0 to the segment .text.__dynamic_cast (i.e the beginning of the segment), you will likely find many functions with a 0 offset like that.

ok, the function might exist then, and I do not know what is happening. It’s a pity I cannot run gdb remotely, I do not have means to do that…

Taking a quick look at the Crazyfiie web site, the unit is designed for C++, and should have no problem running gdb over the SWD link with a simple adaptor cable (maybe trouble doing it actually flying, but you should be able to do a lot of debugging with the system tethered.

Unless they have crippled their version of GCC to only use the so-called ‘embedded C++’, which omits features like this to save resources, it should work.

ok, many thanks for your help.
btw what makes you think that the unit is designed for C++? is there some information on that somewhere?

As for the SWD link, I fear I’ll have to wait until the end of the lockdown, unfortunately. Not a problem though, I can wait, it’s not a vital item.

Thanks again,

Stéphane

The wikipedia article on it says the firmware was designed in C++ with FreeRTOS.

As for the SWD link, it looks they they are still shipping, maybe a bit slower.


richard-damon

    March 30

The wikipedia article on it says the firmware was designed in C++ with FreeRTOS.

Then it’s strange, because when I compile the firmware, it only uses cc. A [citation needed] is needed in the article :wink:

Its’ here btw: https://github.com/bitcraze/crazyflie-firmware/tree/master/src

You can reverse-check the GCC features by using this:
echo /nul | arm-none-eabi-g++.exe -x c++ -dM -E - > _builtin_defines.hpp
on Windows (and also in a similar way on Linux) and check the generated header file for e.g.
#define __EXCEPTIONS 1
and
#define __GXX_RTTI 1

Yep, looks like Wikipedia is wrong there. I tend to trust Wikipedia for simple thing like this until it become important, then it become just a source to point to how to verify.

@hs2 yep, both are defined with my toolchain

I had some free time to go back to this problem.
It turned out that it was entirely my fault, as expected.
I figured that c++ code in headers was working as intended, but not the code in object files that I was compiling externally.
This led me to the insight that I was not compiling them correctly.
Using this small command (*), I could figure out that some files were compiled with -fpic, and some were not, which made the c++ code behave incorrectly.

Case closed, sorry for the noise, and thanks for your help.

(*) echo $(CXXFLAGS) | tr " " “\n” | sort ;

Thank you for taking time to share your solution.

You’re welcome, and I would have been glad to add [solved] to the title of the tread, but I could not find out how to do that…