Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
TFrancuz
PostPosted: Feb 05, 2008 - 02:53 AM
Resident


Joined: Jan 10, 2003
Posts: 551


Hi everybody,
a couple of months ago I started with AVR and c++. It's rather painful adventure, but now most of things seems to work. So I decided to share my little experience, maybe it will be useful for you.
First thing – setup. I use AVR Studio, which is almost working with c++. Almost, because you must manually in project->Configuration options->Custom options set instead of avr-gcc avr-c++.exe to compile any of your c++ files. Just changing the extension to cpp/hpp doesn't work. Remember that if you want to debug your application you need rather to turn off code optimization (-O0). In other case debugging is extremely hard thing to do and confusing. Final compilation can be done with any optimization options.
Next thing to do is to define new and delete operators:
Code:

#include <stdlib.h>

void * operator new(size_t size);
void operator delete(void * ptr);

and implementation:
Code:

void * operator new(size_t size)
{
  return malloc(size);
}

void operator delete(void * ptr)
{
  free(ptr);
}

That's almost all. Almost because if you are using gcc 4.x and newer (I didn't check it with older versions) and you want to use templates, virtual inheritance and so on you must define some additional functions, which is not used now by compiler, but must be present to satisfy linker:
Code:

__extension__ typedef int __guard __attribute__((mode (__DI__)));

extern "C" int __cxa_guard_acquire(__guard *);
extern "C" void __cxa_guard_release (__guard *);
extern "C" void __cxa_guard_abort (__guard *);

Please be sure to define these functions exactly as I showed, I other case gcc could crash during compilation (segmentation fault!), and for sure your program WILL BE NOT working.
Implementation is as follow (very important too):
Code:

int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);};
void __cxa_guard_release (__guard *g) {*(char *)g = 1;};
void __cxa_guard_abort (__guard *) {};

And last thing, if you use pure virtual functions you must define another function:
Code:

extern "C" void __cxa_pure_virtual(void);

and implementation:
Code:

void __cxa_pure_virtual(void) {};

This function is never called in normal operation. The only time this function may get called is if the application calls a virtual function while the object is still being created, which gives undefined behavior. So implementation is not very important for us.
With all this things defined I was able to compile my c++ programs without any problems, and I wish the same to you.
Greetings,
Tomasz.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
JohanEkdahl
PostPosted: Feb 05, 2008 - 10:25 PM
10k+ Postman


Joined: Mar 27, 2002
Posts: 21338
Location: Lund, Sweden

Brilliant!

Attention moderators! Sticky candidate?
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
clawson
PostPosted: Feb 05, 2008 - 11:07 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 69274
Location: (using avr-gcc in) Finchingfield, Essex, England

At the very least I thought Tomasz ought to repost this as a tutorial in the Tutorial Forum so it's doesn't get "lost"

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Feb 06, 2008 - 04:06 AM
10k+ Postman


Joined: Nov 17, 2004
Posts: 14656
Location: Vancouver, BC

Also, someone put the term "CPlusPlus" in it so that it can be found by the search function. Oh look, someone just did Smile

_________________
Regards,
Steve A.

The Board helps those that help themselves.


Last edited by Koshchi on Apr 12, 2008 - 06:09 PM; edited 1 time in total
 
 View user's profile Send private message  
Reply with quote Back to top
steve17
PostPosted: Feb 06, 2008 - 01:35 PM
Raving lunatic


Joined: Sep 07, 2004
Posts: 2989
Location: New York State

I don't have any of the cxa stuff. I never heard of it. My virtual functions aren't pure though.

The only problem I have with virtual functions is they use a huge amount of RAM and quite a bit of program memory also.

I'm currently using gcc version 4.1.2.
 
 View user's profile Send private message  
Reply with quote Back to top
cpluscon
PostPosted: Feb 17, 2008 - 01:06 AM
Raving lunatic


Joined: Jul 10, 2006
Posts: 2687
Location: Minneapolis

These array handlers may be useful too:

Code:
void * operator new[](size_t size)
{
    return malloc(size);
}

void operator delete[](void * ptr)
{
    free(ptr);
}
 
 View user's profile Send private message  
Reply with quote Back to top
kbosak
PostPosted: Jun 19, 2008 - 11:26 PM
Hangaround


Joined: Jan 30, 2008
Posts: 168
Location: Wroclaw, Poland

except the spurious semicolons that generate errors in pedantic + ansi mode,
Code:
int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);};
void __cxa_guard_release (__guard *g) {*(char *)g = 1;};
void __cxa_guard_abort (__guard *) {};
,
you just made a top grade post.

I would also add '-fno-exceptions' and maybe '-ansi --pedantic -Wall' to avoid shooting ourselves in the foot. g++ AVR is uncharted minefield. Any other flags to include?

BTW in order to help newbies finding the g++ and make quicker, here is my example of Project Options/External tools that worked for me:
I:\WinAVR-20071221\bin\avr-g++.exe
I:\WinAVR-20071221\utils\bin\make.exe

The last trap is in the fact that by default printf is not supporting float numbers. However because the C++ projects can be complex, it is wise to go to Project Options/Libraries section, you might want to include
libprintf_flt
libscanf_flt
libc
libm
libobjc
but NOT libprintf_min, libscanf_min

BTW I remember the problem, when a simple code

Code:

int main()
{
   DDRC=0xFF;
   for(;;)
   {
      PORTC=0xFF;
      _delay_us(1);
      PORTC=0x00;
      _delay_us(1);
   }
}

...was not working just because I have been instancing a static class object in one of include files. It took me the whole night to find the problem, hopefully my suspicions pointed onto global objects very early. The funny part was, that everything worked when the project was big. Once I have simplified (!!!) main() function to the code above, it stopped working (freeze before main). I have hunted down the statically instantiated class in one of includes, and moved it as static object to main().
This time, however, it started complaining about lacking __cxa_guard_acquire, __cxa_guard_release.
So remember, when you make static class object in global scope, without providing these functions, the code will fail silently, depending on the actual size of the project and many other factors.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
atomicdog
PostPosted: Jun 20, 2008 - 02:10 AM
Posting Freak


Joined: Jan 14, 2008
Posts: 1169
Location: San Diego

kbosak wrote:

I would also add '-fno-exceptions' and maybe '-ansi --pedantic -Wall' to avoid shooting ourselves in the foot. g++ AVR is uncharted minefield. Any other flags to include?



These will help with the code size.
Code:

-ffunction-sections
-Wl,--gc-sections



http://www.avrfreaks.net/index.php?name ... mp;t=64513

_________________
~~John
TWI C source code
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Levenkay
PostPosted: Jun 21, 2008 - 10:28 AM
Resident


Joined: Dec 20, 2007
Posts: 964
Location: Portland, Oregon, USA

TFrancuz wrote:
Hi everybody,
a couple of months ago I started with AVR and c++. It's rather painful adventure, but now most of things seems to work. So I decided to share my little experience, maybe it will be useful for you.
First thing – setup. I use AVR Studio, which is almost working with c++. Almost, because you must manually in project->Configuration options->Custom options set instead of avr-gcc avr-c++.exe to compile any of your c++ files. Just changing the extension to cpp/hpp doesn't work. Remember that if you want to debug your application you need rather to turn off code optimization (-O0). In other case debugging is extremely hard thing to do and confusing. Final compilation can be done with any optimization options.
Next thing to do is to define new and delete operators:
Code:

#include <stdlib.h>

void * operator new(size_t size);
void operator delete(void * ptr);

and implementation:
Code:

void * operator new(size_t size)
{
  return malloc(size);
}

void operator delete(void * ptr)
{
  free(ptr);
}


That's almost all.
... (abridged) ...

With all this things defined I was able to compile my c++ programs without any problems, and I wish the same to you.
Greetings,
Tomasz.


This is pretty impressive (I thought I knew a thing or two about C++, but "guard"s are a new one on me).

One thing I think you have missed, though, is that delete operators are supposed to safely do nothing if they're passed a NULL pointer. So your sample implementation of delete should look like this:
Code:

void operator delete(void * ptr)
{
  if (ptr)
    free(ptr);
}
 
 View user's profile Send private message  
Reply with quote Back to top
kbosak
PostPosted: Jun 21, 2008 - 02:21 PM
Hangaround


Joined: Jan 30, 2008
Posts: 168
Location: Wroclaw, Poland

Quote:

One thing I think you have missed, though, is that delete operators are supposed to safely do nothing if they're passed a NULL pointer. So your sample implementation of delete should look like this:
Code:

void operator delete(void * ptr)
{
  if (ptr)
    free(ptr);
}

This is a surprise to me. I always believed since 1990 that free(NULL) is always OK, even if I almost never wrote code using this. http://www.winehq.org/pipermail/wine-pa ... 31544.html
says:
ANSI-C Standard:
----------------
The ANSI standard ANSI X3.159-1989 "Programming Language C." specifies
that free(NULL) is a no op.
"free deallocates the space pointed to by p: it does nothing if p is NULL."
Quoted from "The C Programming Language" second edition by Kernighan and
Ritchie with the subtitle "ANSI C".

This would indicate that your protection is superfluous.
BTW for nitpickers that like excess safety, the code should be:
Code:
if(ptr!=NULL)
{
    free(ptr);
}

because (oh there are long and useless discussions about that) NULL dont have to be 0 numerically.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Lajon
PostPosted: Jun 21, 2008 - 05:03 PM
Posting Freak


Joined: Mar 12, 2004
Posts: 1210
Location: Linköping, Sweden

Quote:
because (oh there are long and useless discussions about that) NULL dont have to be 0 numerically.
Actually NULL has to be 0 in C++ (and many C++ programmers avoid using NULL).

http://www.research.att.com/~bs/bs_faq2.html#null
/Lars
 
 View user's profile Send private message  
Reply with quote Back to top
Levenkay
PostPosted: Jun 21, 2008 - 08:34 PM
Resident


Joined: Dec 20, 2007
Posts: 964
Location: Portland, Oregon, USA

kbosak wrote:

This is a surprise to me. I always believed since 1990 that free(NULL) is always OK, even if I almost never wrote code using this. http://www.winehq.org/pipermail/wine-pa ... 31544.html
says:
ANSI-C Standard:
----------------
The ANSI standard ANSI X3.159-1989 "Programming Language C." specifies
that free(NULL) is a no op.
"free deallocates the space pointed to by p: it does nothing if p is NULL."
Quoted from "The C Programming Language" second edition by Kernighan and
Ritchie with the subtitle "ANSI C".

This would indicate that your protection is superfluous.


Wualll, I'll be darned. This is one of those superstitious "safety measure" habits that reinforce themselves; like wearing a Shriners hat to ward off flying squirrel attacks. You wear the hat, and voilla! no squirrels! After awhile, the two seem to be correlated. No particular harm done, but you DO look silly..

I'd always assumed that free()ing NULL was bad medicine, and even have dim recollection of crash dumps from our embedded code when it tried to do so (but we used an extremely old compiler). Anyway, I thought the safety of delete-ing NULL pointers was unique to C++.
 
 View user's profile Send private message  
Reply with quote Back to top
kbosak
PostPosted: Jun 21, 2008 - 10:53 PM
Hangaround


Joined: Jan 30, 2008
Posts: 168
Location: Wroclaw, Poland

Quote:
and many C++ programmers avoid using NULL

I am sorry but this is void* argument.
Most programmers are not compiler developers and most compiler developers don't care aboutev erything the Standard says, not to mention about being familiar with avr-g++.

There is more than that:
Code:
malloc(0)

in practice behaves like
Code:
new ptr[0]

The trick is that C++
Code:
new ptr[0]
is standard sanctioned: returning NONNULL, properly aligned pointer for a single element!
Code:
malloc(0)
returning nonnull may or may not be standard.
This helps implementing some dynamic data structures, I believe.
http://gcc.gnu.org/ml/libstdc++/2005-02/msg00167.html
"
The standard defines that allocators
(and operator new) may be asked for zero bytes. They must return an
address different from any other address that they have returned that
haven't since been released. (That disallows returning 0.) Most
implementations treat a call to operator new(0) identically to operator
new(1).
"


Last edited by kbosak on Jun 21, 2008 - 11:02 PM; edited 1 time in total
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
steve17
PostPosted: Jun 21, 2008 - 11:00 PM
Raving lunatic


Joined: Sep 07, 2004
Posts: 2989
Location: New York State

The use of the C++ delete operator in an AVR program is generally a waste of memory, and so is using malloc and free.

It's only when you want to dynamically "churn the heap" that it is required. To put it another way, if the equivalent C program would use malloc and free, then your C++ program would also use them, via new and delete.

Balancing each new with a delete is considered good practice in programs that run on PCs, but it serves no purpose on AVR programs where there is no shutdown except a hardware reset. Actually I question if it has any purpose in embedded programs that run on PCs, but I do it just because it's "good practice".

On an AVR, just "new" everything at startup and run with what you have until the end of time or reset/powerdown, whichever comes first.
 
 View user's profile Send private message  
Reply with quote Back to top
kbosak
PostPosted: Jun 21, 2008 - 11:06 PM
Hangaround


Joined: Jan 30, 2008
Posts: 168
Location: Wroclaw, Poland

Quote:
Balancing each new with a delete is considered good practice in programs that run on PCs, but it serves no purpose on AVR programs where there is no shutdown except a hardware reset.

Sorry, short-sighted idea. In fact many efficient linear algebra algorithms require special handling of sparse matrices for max speed. This calls for dynamic data structures. In order to keep implementation of those data structures clean, dynamic memory allocation is necessary. This is the major benefit of using C/C++ over FORTRAN in scientific programming. Using advanced linear algebra/geometry/fitting/optimization algoritms is very popular in many areas, just to mention GPS receivers. GPS receivers tend to run on ARM7, but simpler versions can easily run on AVR.

Let's put it this way: you can get rid of malloc and free completely. But one day, you will write a complex data structure, that uses fixed memory pool. Next day you will find that in runtime this structure hides 20% of innovatory code and 80% of code that immitates malloc's functionality.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
steve17
PostPosted: Jun 22, 2008 - 01:23 AM
Raving lunatic


Joined: Sep 07, 2004
Posts: 2989
Location: New York State

kbosak wrote:
Sorry, short-sighted idea.


So you are saying that any C programmer that doesn't include malloc and free in all his programs is short-sighted?

All I'm saying is C++ doesn't need malloc and free any more than C programs. If a program needs it, use it. Otherwise don't. Of course if you have excessive program memory then it doesn't matter. I rarely find myself in that situation though.
 
 View user's profile Send private message  
Reply with quote Back to top
kbosak
PostPosted: Jun 22, 2008 - 01:39 AM
Hangaround


Joined: Jan 30, 2008
Posts: 168
Location: Wroclaw, Poland

steve17 wrote:
kbosak wrote:
Sorry, short-sighted idea.


So you are saying that any C programmer that doesn't include malloc and free in all his programs is short-sighted?

All I'm saying is C++ doesn't need malloc and free any more than C programs. If a program needs it, use it. Otherwise don't. Of course if you have excessive program memory then it doesn't matter. I rarely find myself in that situation though.

I was commetning this:
Quote:
The use of the C++ delete operator in an AVR program is generally a waste of memory, and so is using malloc and free.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Broxbourne
PostPosted: Jun 22, 2008 - 06:29 AM
Hangaround


Joined: Nov 16, 2005
Posts: 341
Location: Calgary, Alberta, Canada

OT:
Quote:
GPS receivers tend to run on ARM7, but simpler versions can easily run on AVR.

That is a somewhat misleading statement. Definition of 'simpler' and 'easily' required.
 
 View user's profile Send private message  
Reply with quote Back to top
kbosak
PostPosted: Jun 22, 2008 - 10:18 PM
Hangaround


Joined: Jan 30, 2008
Posts: 168
Location: Wroclaw, Poland

Broxbourne wrote:
OT:
Quote:
GPS receivers tend to run on ARM7, but simpler versions can easily run on AVR.

That is a somewhat misleading statement. Definition of 'simpler' and 'easily' required.

You can use Student-Lockroom programming to achieve the result.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Broxbourne
PostPosted: Jun 23, 2008 - 01:37 AM
Hangaround


Joined: Nov 16, 2005
Posts: 341
Location: Calgary, Alberta, Canada

Quote:
You can use Student-Lockroom programming to achieve the result.

Thanks, I didn't know that.
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits