EmbeddedRelated.com
Forums

Memory allocation with gcc on AVR (Arduino)

Started by bitrex August 9, 2016
So the Arduino environment has the following template code when you 
start up a new project:

void setup()
{
//code to be run at startup
}

void loop()
{
//run forever
}

Suppose I define a class at the top of my "sketch" like so:

struct Foo { void do_it() { return 1; } };

I then try to create a "global" instance of the class outside the 
"setup" section:

Foo foo;

This compiles fine, except that when you attempt to use "do_it" from 
within the "loop" section the code doesn't seem to execute properly.

If I do the following:

Foo *foo;

void setup()
{
   foo = new Foo;
}

It works as expected, but then...something? is being placed into heap 
memory. My expectation would be that on a Harvard architecture uP, the 
only things being put on the heap when a new object is instantiated 
would be the non-const class member variables with static storage 
duration, as the code has its own program memory, but that doesn't 
appear to be what is happening.

Any insight into what avr-gcc is actually doing in this case would be 
appreciated.
On 08/09/2016 11:55 AM, bitrex wrote:
> So the Arduino environment has the following template code when you > start up a new project: > > void setup() > { > //code to be run at startup > } > > void loop() > { > //run forever > } > > Suppose I define a class at the top of my "sketch" like so: > > struct Foo { void do_it() { return 1; } }; >
Sorry, that should be: struct Foo { int do_it() { return 1; } };
On 09/08/16 17:55, bitrex wrote:
> So the Arduino environment has the following template code when you > start up a new project: > > void setup() > { > //code to be run at startup > } > > void loop() > { > //run forever > } > > Suppose I define a class at the top of my "sketch" like so: > > struct Foo { void do_it() { return 1; } }; > > I then try to create a "global" instance of the class outside the > "setup" section: > > Foo foo; > > This compiles fine, except that when you attempt to use "do_it" from > within the "loop" section the code doesn't seem to execute properly.
What do you mean "the code doesn't seem to execute properly" ? The function merely returns 1, so there is not much to go wrong. Can you post the entire code?
> > If I do the following: > > Foo *foo; > > void setup() > { > foo = new Foo; > } > > It works as expected, but then...something? is being placed into heap > memory. My expectation would be that on a Harvard architecture uP, the > only things being put on the heap when a new object is instantiated > would be the non-const class member variables with static storage > duration, as the code has its own program memory, but that doesn't > appear to be what is happening.
The struct has size 1, even though it has no data members (as 1 is the minimum size a struct/class can have).
> > Any insight into what avr-gcc is actually doing in this case would be > appreciated.
On 08/09/2016 05:55 PM, bitrex wrote:
> So the Arduino environment has the following template code when you > start up a new project: > > void setup() { //code to be run at startup } > > void loop() { //run forever } > > Suppose I define a class at the top of my "sketch" like so: > > struct Foo { void do_it() { return 1; } }; > > I then try to create a "global" instance of the class outside the > "setup" section: > > Foo foo; > > This compiles fine, except that when you attempt to use "do_it" from > within the "loop" section the code doesn't seem to execute properly. >
It `should' work... [..]
> Any insight into what avr-gcc is actually doing in this case would > be appreciated.
Have a look at the assembler output. If that thing is just a wrapper for gcc, it should be easy to get at. AFAIR there were two variants. one for each file and one representing the final binary. You 'll want the latter, so you can check if the init code is doing sthg funny. Map file may be helpful, too.
On 9.8.16 18:55, bitrex wrote:
> So the Arduino environment has the following template code when you > start up a new project: > > void setup() > { > //code to be run at startup > } > > void loop() > { > //run forever > } > > Suppose I define a class at the top of my "sketch" like so: > > struct Foo { void do_it() { return 1; } }; > > I then try to create a "global" instance of the class outside the > "setup" section: > > Foo foo; > > This compiles fine, except that when you attempt to use "do_it" from > within the "loop" section the code doesn't seem to execute properly. > > If I do the following: > > Foo *foo; > > void setup() > { > foo = new Foo; > } > > It works as expected, but then...something? is being placed into heap > memory. My expectation would be that on a Harvard architecture uP, the > only things being put on the heap when a new object is instantiated > would be the non-const class member variables with static storage > duration, as the code has its own program memory, but that doesn't > appear to be what is happening. > > Any insight into what avr-gcc is actually doing in this case would be > appreciated.
To see the assembly code of the whole program: avr-objdump -D myfile.elf >myfile.dis Substitute the linked file name instead of myfile. To see the assembly code generated for a module by gcc, add to gcc command line: '-Wa,-adhlms=mymodule.lst'. Substitute the module name instead of mymodule. You can leave the quotes out if the file name does not contain spaces or other weird. If you're using make you can use in the compile rule: -Wa,-adhlms=$(@:.o=.lst) -- -TV