Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Are Vtables Not Being Implemented Correctly On Embedded Platform?

I am developing code for an embedded system (specifically, the PSoC 5, using PSoC Creator), and writing in C++.

While I've overcome most hurdles with using C++ , first off compiling in C++ using the compiler flag -x c++, defining the new and delete operators, making sure exceptions aren't thrown with the compiler flag -fno-exception, I've come to a brick wall when it comes to using virtual functions.

If I try and declare a virtual function, the compiler gives me the error undefined reference to "vtable for __cxxabiv1::__class_type_info". The only way to get around this is to use the compiler flag -fno-rtti, which prevents the error and makes it compile successfully. However, if I do that, the embedded program crashes when trying to run the overloaded virtual function, and I'm thinking this is because the vtable does not exist.

I don't see why you shouldn't be able to implement vtables on an embedded platform, since all it is a extra space in memory before or after member objects (depending on the exact compiler).

The reason I am trying to use virtual functions is because I am wanting to use FreeRTOS with C++, and other people have implemented this by using virtual functions (see http://www.freertos.org/FreeRTOS_Support_Forum_Archive/July_2010/freertos_Is_it_possible_create_freertos_task_in_c_3778071.html for the discussion, and https://github.com/yuriykulikov/Event-driven_Framework_for_Embedded_Systems for a well written embedded C++ FreeRTOS framework)

like image 380
gbmhunter Avatar asked Apr 24 '13 02:04

gbmhunter


1 Answers

The fact that the error message refers to a class named __cxxabiv1 suggests that you are not linking against the correct C++ runtime for your platform. I don't know anything about PSoC, but on more "normal" platforms, this sort of error could happen if you used the gcc (resp. clang) command at link-time instead of g++ (resp. clang++); or under handwavey circumstances if you used -lc++ without -stdlib=libc++ or -lstdc++ without -stdlib=libstdc++.

Use the -v option to examine your linker command line, and try to find out exactly which C++ runtime library it's pulling in. It'll probably be named something like libcxxabi or libcxxrt.

This guy here gives step-by-step instructions for compiling C++ in PSoC Creator; but he never figured out how to link with a C++ runtime library, so all his tips are focused on how to remove C++isms from your code (-fno-rtti, -fno-exceptions,...). I agree that there doesn't seem to be any information online about how to actually use C++ with PSoC.

For this specific error, you could always try defining the missing symbol yourself:

// file "fix-link-errors.cpp"
namespace __cxxabiv1 {
    class __class_type_info {
        virtual void dummy();
    };
    void __class_type_info::dummy() { }  // causes the vtable to get created here
};

Or many linkers have the ability to define undefined symbols as 0x0 through command-line options such as -C or --defsym. However, that's not only a Bad Idea but also inconvenient, because you'd have to figure out what the actual (mangled) name of the vtable object is, and the linker didn't tell you that. (This being GCC, it's probably something like __ZTVN10__cxxabiv117__class_type_infoE.)

Either of those "solutions" would result in horrible crashes if the program ever tried to do anything with the vtable; but they'd shut the linker up, if that's all you cared about and you knew the program would never actually use RTTI. But in that case, it should be sufficient to use -fno-rtti consistently on your entire project.

What, specifically, goes wrong when you use -fno-rtti?

like image 63
Quuxplusone Avatar answered Sep 21 '22 12:09

Quuxplusone