User account creation filtered due to spam.

Bug 43745 - [avr] g++ puts VTABLES in SRAM
Summary: [avr] g++ puts VTABLES in SRAM
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.7.0
: P4 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
Keywords: addr-space, missed-optimization
Depends on: 49868
  Show dependency treegraph
Reported: 2010-04-13 08:15 UTC by Tomasz Francuz
Modified: 2015-12-08 04:10 UTC (History)
10 users (show)

See Also:
Target: avr
Known to work:
Known to fail:
Last reconfirmed: 2012-01-07 00:00:00


Note You need to log in before you can comment on or make changes to this bug.
Description Tomasz Francuz 2010-04-13 08:15:31 UTC
On AVR target g++ generates code which copies object’s VTABLES from FLASH to SRAM wasting the memory. Due to the Harvard architecture of AVR processors the solution is not trivial. This behavior can be observed in any c++ program which has object with virtual method, e.g:
Class test
	virtual void example();

The VTABLE of class test will be generated in FLASH and next copied to SRAM, any reference to virtual example() method will take the method address from SRAM.
Comment 1 Eric Weddington 2010-04-14 19:52:53 UTC
What is your suggestion?
Comment 2 Tomasz Francuz 2010-04-14 20:39:55 UTC
(In reply to comment #1)
> What is your suggestion?

Because VTABLES are generated during compile time and they are const data there is no need to copy them into SRAM. Appropriate addresses of virtual methods can be read directly from FLASH and used to make indirect call as usual. As far as I know the problem is that AVR port of gcc doesn’t have appropriate isns to do that. The problem is extremely important because for example my program uses 964 bytes of SRAM, from which 860 bytes are used for VTABLES (wasted). This is a typical situation for any C++ program on AVR.
The only problem is speed penalty, LD instruction on AVR takes 1 cycle, whereas LPM instruction needed for FLASH access 3 cycles, which gives total 2 or 6 cycles to read virtual method address respectively. So probably the best solution is to add another gcc option (or pragma) to choose between storing VTABLES only in FLASH (slower code execution) or moving it to SRAM (faster execution for the cost of higher SRAM memory occupation).

Comment 3 Michał Walenciak 2011-02-06 19:30:06 UTC
Another idea is to simplify virtual calls.
At the final link, probably most of the virtual calls could be converted into regural calls (as whole program is known, and some base classes may have only one (or zero) descendant, so all virtual calls will affect only it).
Comment 4 Georg-Johann Lay 2011-11-21 15:50:11 UTC
(In reply to comment #0)

> Class test
> {
>     virtual void example();
> };

Would you please post some real code that shows the problem and actually *compiles* with, e.g.

avr-g++ -c vtable.cpp

instead of the lines above that trigger syntax error?
Comment 5 Tomasz Francuz 2011-11-24 21:56:17 UTC
Ok, here is the code:
class test
  test() {};
  virtual void vfunction();

void test::vfunction()

int main()

After compilation 6 bytes of SRAM is occupied by test object vtable. Here is a resulting part of map file:
 .data          0x00800100        0x0 c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib/avr51/crtm128.o
 .data          0x00800100        0x6 gpp.o
                0x00800100                vtable for test
 .data          0x00800106        0x0 c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/avr51\libgcc.a(_exit.o)
Comment 6 Riccardo Manfrin 2012-11-29 11:57:58 UTC
I'm also experiencing this issue and would like a patch or something to be able to directly access vtables from flash on need.
I'd like to know if anyone has found even a temporary fix to that (even though it means losing to a non portable solution/bad code ...).
Comment 7 Côme David 2013-04-26 11:54:03 UTC

I'm currently facing the exact same problem. I have a several classes with virtual methods and 50% of my RAM is taken by the vtables of these classes.

I'm still willing to know if someone has come up with a solution/workaround for this.

Thank you !
Comment 8 Georg-Johann Lay 2013-06-11 13:17:44 UTC
This needs extensions in the C++ front => Component = c++
Comment 9 Jackie Rosen 2014-02-16 13:17:02 UTC Comment hidden (spam)
Comment 10 Oscar García 2015-12-07 18:21:47 UTC
This problem can be mitigated using "pointer to interfaces".

Instead of:

class A
void FncEatingVTableRamA();
void FncEatingVTableRamB();
void FncEatingVTableRamC();
void FncEatingVTableRamD();
void FncEatingVTableRamE();
void FncEatingVTableRamF();

virtual void FncASingleVirtualFunctionPutAllVTableInRam();

I use to change it to:
class IVirtual
virtual void FncASingleVirtualFunctionPutAllVTableInRam();

class ANotInRamVTable
IVirtual* pVirtual;
    A(IVirtual* pV)
    void FncEatingVTableRamA();
    void FncEatingVTableRamB();
    void FncEatingVTableRamC();
    void FncEatingVTableRamD();
    void FncEatingVTableRamE();
    void FncEatingVTableRamF();

void FncNOTVirtual()

class DerivedA:public IVirtual //Not derived actually
//REALIZE DerivedA will have VTABLE in ram because of IVirtual

    ANotInRamVTable aNotInRam;

    void FncASingleVirtualFunctionPutAllVTableInRam();

It will not solve the problem, and I agree this is an important obstacle to make reusable/scalable code in reduced-RAM environments but it helps sometimes.