Problems with virtual functions

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Problems with virtual functions

      New

      Hello,

      I'm working with nRF SDK 14.2 and the NRF52832 Dev kit, developing in C++. I have a base class with a few virtual functions and a derived class that I'm using. The code compiled, linked and flashed fine, but in debugging found that the virtual functions were not working (virtual calls in the base class calling the base implementation rather than the derived implementation).

      I tried turning on rtti in the compile, in case this was required to enable virtual functions, but that is producing the following linker error:

      undefined reference to `vtable for __cxxabiv1::__si_class_type_info'

      Searching I've done suggests the linker needs to be directed to link to C++ runtime ( -lstdc++ ) but this option does not appear to be supported by the SEGGER linker. Linker version info is below.
      C:\Program Files\SEGGER\SEGGER Embedded Studio for ARM 4.12\gcc\arm-none-eabi\bin>ld --version
      GNU ld (GNU Binutils) 2.30.0.20180329

      The post was edited 1 time, last by smithron99 ().

    • New

      Hello,

      Thank you for your inquiry.

      smithron99 wrote:

      Searching I've done suggests the linker needs to be directed to link to C++ runtime ( -lstdc++ ) but this option does not appear to be supported by the SEGGER linker. Linker version info is below.
      Correct, see here: Segger Linker 2.25
      However Embedded Studio also comes with the gcc Linker which should support this.

      Best regards,
      Nino
      Please read the forum rules before posting: Forum Rules

      Keep in mind, this is not a support forum. Its main purpose is user to user interaction.
      Our engineers will try to answer your questions between their projects if possible but this can be delayed by longer periods of time.
      Should you be entitled to support contact us per e-mail.
      Alternatively our support ticketing system can be used as well: segger.com/ticket/
    • New

      Hmmm. A few odd things:
      1. When I went into settings I found I already had the linker set to "GNU"
      2. When I re-enabled rtti, the undefined reference was gone.
      3. Virtual functions still aren't working properly. When the derived class is constructed, I see this call sequence:
        • Derived()->PowerCurve()->init()->floor()->delayFromPower()->maxCycles()

        • the only method in this chain overridden by the derived class is maxCycles(), but in this call chain, the base class implementation is called
      Here's the base class definition:

      Source Code

      1. class PowerCurve
      2. {
      3. protected:
      4. static const long CYCLE_MICROS = 8333;
      5. static long _highBuffer;
      6. static long _lowBuffer;
      7. long _floor;
      8. long _maxSpeed;
      9. public:
      10. PowerCurve(long highBuffer, long floor, long maxSpeed)
      11. {
      12. init(highBuffer, floor);
      13. _maxSpeed = maxSpeed;
      14. }
      15. virtual ~PowerCurve() {}
      16. void init(long highBuffer, long floor);
      17. virtual void highBuffer(long buffer);
      18. static long highBuffer(void)
      19. {
      20. return _highBuffer;
      21. }
      22. long delayFromPower(long power);
      23. virtual long delayFromSpeed(long speed)
      24. {
      25. return _lowBuffer;
      26. }
      27. void floor(long aFloor);
      28. long floor(void)
      29. { return _floor; }
      30. static long lowBuffer(void)
      31. { return _lowBuffer; }
      32. virtual long maxCycles(void);
      33. int power(long delay);
      34. long maxSpeed(void)
      35. { return _maxSpeed; }
      36. virtual std::string toString(void);
      37. };
      Display All
      So there are five virtual functions. I'm not sure how to examine the generated vtable from the linker, but looking at the locals in the debugger, it looks (?) like only the destructor is present in the vtable. See the attached image. I've also attached full source for the base and derived classes. The derived instance is allocated on the stack. Declared in main() like so:

      LEDCurve powerCurve( 1000, 500 );

      Images
      • vptr.jpg

        54.21 kB, 450×370, viewed 2 times
      Files
    • New

      If the debugger is telling the truth, then it looks like the vtable is fully populated, but not correct (see attached image). Not sure why the destructor is showing at both offsets [0] and [1]. Could the problem be that this is happening in the base class constructor, and the derived class is not deemed constructed yet? Maybe the correct vtable is not in play yet? This code is borrowed from an existing working project, but built with a different compiler. Hmmm..
      Images
      • vtable.jpg

        156.53 kB, 1,504×380, viewed 4 times