cancel
Showing results for 
Search instead for 
Did you mean: 

Calling virtual function of class which derives from two base classes crashes with hardfault

RKöll.2374
Associate II

I have found a problem when deriving a class from two base classes.

class BaseA

{

public:

BaseA() {}

virtual int GetNumber() const {return 42;}

};

class BaseB

{

public:

BaseB() {}

virtual int32_t MathConfuscator(int32_t input) {return input * 97 % 5;}

};

class DerivedC : public BaseA, public BaseB

{

public:

DerivedC() {}

int GetNumber() const override {return 10;}

int32_t MathConfuscator(int32_t input) override {return input * 10;}

};

Running these classes in a program e.g.:

int main()

{

DerivedC myDerive;

int64_t myTick = 4078;

int32_t tmp = ((BaseA*)&myDerive)->GetNumber();

if(myTick == ((BaseB*)&myDerive)->MathConfuscator(tmp))

return 1;

}

The first function call GetNumber() is executed correctly and jumps into the DerivedC function while the MathConfuscator function call crashes with a hard fault.

I have tested this on an STM32G031 Nucleo-32 evaluation board using the STM32G031K8T6 procesor. The compiler chain is "9 2020-q2-update".

To me it is unclear why I do get a hard fault when running this code. If the code would be wrong I would expect a compiler error or a linker problem.

Can you give me a hint what I am doing wrong or where I might look for an answer to this problem?

Thanks,

Rasmus Kölln

1 ACCEPTED SOLUTION

Accepted Solutions
KnarfB
Principal III

works here for a similar chip (the closest I have) and default settings:

arm-none-eabi-g++ "../Core/Src/moin.cpp" -mcpu=cortex-m0plus -std=gnu++14 -g3 -DSTM32G071xx -DUSE_HAL_DRIVER -DDEBUG -c -I../Core/Inc -I../Drivers/STM32G0xx_HAL_Driver/Inc -I../Drivers/STM32G0xx_HAL_Driver/Inc/Legacy -I../Drivers/CMSIS/Device/ST/STM32G0xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -fno-exceptions -fno-rtti -fno-use-cxa-atexit -Wall -fstack-usage -MMD -MP -MF"Core/Src/moin.d" -MT"Core/Src/moin.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Core/Src/moin.o"

Anyway, the result is 100.

View solution in original post

4 REPLIES 4
KnarfB
Principal III

Could you try proper C++ casting, not old C type pointer casting.

RKöll.2374
Associate II

Changing the code of the main function into

int main()

{

DerivedC myDerive;

int64_t myTick = 4078;

int32_t tmp = dynamic_cast<BaseA*>(&myDerive)->GetNumber();

if(myTick == dynamic_cast<BaseB*>(&myDerive)->MathConfuscator(tmp))

return 1;

}

did not change anything on the behavior, I still end up with a hard fault.

The assmebler code of both versions crash at the same address on the same instruction:

stmia r0!, {r2}

where r0 and r2 have the same value.

KnarfB
Principal III

works here for a similar chip (the closest I have) and default settings:

arm-none-eabi-g++ "../Core/Src/moin.cpp" -mcpu=cortex-m0plus -std=gnu++14 -g3 -DSTM32G071xx -DUSE_HAL_DRIVER -DDEBUG -c -I../Core/Inc -I../Drivers/STM32G0xx_HAL_Driver/Inc -I../Drivers/STM32G0xx_HAL_Driver/Inc/Legacy -I../Drivers/CMSIS/Device/ST/STM32G0xx/Include -I../Drivers/CMSIS/Include -O0 -ffunction-sections -fdata-sections -fno-exceptions -fno-rtti -fno-use-cxa-atexit -Wall -fstack-usage -MMD -MP -MF"Core/Src/moin.d" -MT"Core/Src/moin.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Core/Src/moin.o"

Anyway, the result is 100.

RKöll.2374
Associate II

Dear KnarfB,

I have compiled the code with the flags you have put and it works fine now.

I did not have the flag mcpu=cortex-m0plus in my compiler flags. I had -mthumb instead. Changing that flag did the trick - so thanks a lot for posting the compiler flags.