I was curious what folks in the embedded development world might see as their key persuasion to avoid using C++ for embedded applications. Is it size? Of particular features? Is it Speed? Perhaps general memory footprint because of poor implementations (in some places) of certain features, like templates or exception handling? Other? I've heard some discussion that one reason could be the number of embedded programmers who are still using assembly language, or slowly moving up to C, and see C++ as too far-reaching a learning curve. Is that related? Thanks, B
1. C++ is very implicit and therefor dangerous. Programers must (as always) know what to do and what to use and more important what not to use (overloading of casting, calling polymorphic function in constructors, using bad design with overheads not reasonable ). One should be very experienced. 2. The main benefit of C++ is in the application side. C++ have many benefits that do not come into action if your very near the hardware (usually) . such benefit is avoiding sending all those parameters by function because the object know them already, it was constructed or initialized with the parameters (other way to do that is with annoying arrays and passing Id's). when you write drivers you usually do it C style and you prefer that your colleague would not touch C++ and make annoying Bugs. 3. In Our Embedded project with vxWorks, I use a bit of C++ when it convenient, the people around me do not. if there isn't a real benefit it should not be used. but I do think that using the compiler with strict type check is good. in future when the need to add polymorphic feature will arouse we might use much more C++ but very carefully. meanwhile the basic is C (I do miss the syntax of calling method in Class). Don't shoot your leg off by using to much of C++, your fellow men might not know about the pits of C++ ( i already forgot some of them and believe me there are many ...). maybe with good JITs will do it the Java way.
On Thu, 13 Aug 1998 09:17:39 +0200, Saffi Hartal wrote: >1. C++ is very implicit and therefor dangerous. Programers must (as always) >know what to do and what to use and more important what not to use >(overloading of casting, calling polymorphic function in constructors, >using bad design with overheads not reasonable ). One should be very >experienced. This is true of any language, and not limited to C++. Assembler and C have pitfalls as well. A professional programmer using C++ for embedded work should be familiar with Meyer's _Effective C++_ books. I've also found C++ Report to be a good resource for advanced topics. >2. The main benefit of C++ is in the application side. C++ have many >benefits that do not come into action if your very near the hardware >(usually) . such benefit is avoiding sending all those parameters by >function because the object know them already, it was constructed or >initialized with the parameters (other way to do that is with annoying >arrays and passing Id's). when you write drivers you usually do it C style >and you prefer that your colleague would not touch C++ and make annoying >Bugs. The benefit of using C++, like that of any language, is to provide syntactic constructs that eliminate tedious error-prone busy-work like boilerplate code. Even assembly language exists to eliminate the error-prone construction of machine language bit by bit. The Windows world has hidden some of this boilerplate generation behind "wizards", which provides yet another layer of tool to help avoid errors. >3. In Our Embedded project with vxWorks, I use a bit of C++ when it >convenient, the people around me do not. if there isn't a real benefit it >should not be used. but I do think that using the compiler with strict type >check is good. in future when the need to add polymorphic feature will >arouse we might use much more C++ but very carefully. meanwhile the basic is >C (I do miss the syntax of calling method in Class). One of the founding objectives of C++ was that you don't pay for what you don't use. There's no reason not to use C++ as a C-lite, if all you want is the simpler syntactic niceties. The thing I miss most when forced back into C is the requirement of declaring variables at the top of a block instead of where they're first used. I also miss the ability to stuff a declaration into the "for" construct. I think the real objection to using C++ in embedded projects is the relatively chubby implementations. Development environments primarily target diskful systems where storage is cheap. There's not much pressure to create slim binaries that reuse common code sequences and trim unused code from modules. The embedded world is more subject to costs of mass production, where squeezing the code footprint down will result in significant reduction of hardware cost when viewed over many units. I don't see speed as a big issue, as one can always profile an app and recode the bandwidth pigs in hand-tuned assembler. Such code is likely to be a small part of any application. > maybe with good JITs will do it the Java way. Now there's a whole 'nother can of worms. What issues does C++ share with Java that make both undesirable for embedded applications? Where might one use one in favor of the other? (My point is not to start a language war but to compare tools that could dovetail to serve different parts of an application's needs.) Kenneth Porter Systems Engineer Kensington Laboratories, Inc. 750 National Court Richmond, CA 94804-2008 Voice: 510-620-0235 FAX: 510-233-5544 mailto:kenneth_porter@kensingtonlabs.com http://www.kensingtonlabs.com
[I'm posting my reply to the list as I'm sure others are following the general discussion. Also, please set your mail program to limit line lengths to 72 columns.] On Sun, 16 Aug 1998 18:17:17 +0200, Saffi Hartal wrote: >Kenneth I might be mistaken in some of the things i write but it is the best of my >knowledge without looking up and checking ... . > >C has it's pitfalls also, but the people i work with know already to avoid them but they don't know with C++. >the books you write about I'm not familiar with (I'm not really familiar with any books except Dr. Dobb's which i read sometimes), if you have a recommended file\FAQ or link to a sight I'll be happy. As I said before, look at Meyers' books and C++ Report. When I need a quick answer to an advanced question, I use news:comp.lang.c++.moderated . And, of course, if it's related to embedded systems, there's this list. >>The benefit of using C++, like that of any language, is to provide >>syntactic constructs that eliminate tedious error-prone busy-work like >>boilerplate code. Even assembly language exists to eliminate the >>error-prone construction of machine language bit by bit. The Windows >>world has hidden some of this boilerplate generation behind "wizards", >>which provides yet another layer of tool to help avoid errors. >What is boilerplate ?! . The tedious stuff that one writes over and over. > i understand the fun and ease of use with constructors instead of calling initialization functions. i made a log.h log.c modules that each module automatically register and hid log level is controlled from the outside (if you want tell me it's nice and easy a bit of macro stuff and a little semaphore for avoiding multiprocess text become garbage on the screen ). the C++ ability to call function at variable initialization (like constructor) from outside function scope made the automated registration of modules possible. >For me Assembly is not a language, it's a torment. and i hate wizards. i know a bit about MFC work and it's efficient but it's not very clean (many people like it, i don't though i appreciate the code the protects the New and Delete from overrun and such, if you don't have one on your platform i have found one called Fortify it's Ansi and it looks great). >As i wrote, i use C++ in my code, but my fellowmen which i work with don't, >the interface between modules is C. it is a bit annoying. so I as you do declare what i want where i want. >I think that if they would have used C++ we would have encountered a major delay in the Project. (which is the worst thing that could happen). There's no point to using a tool you don't understand. One approach here is to use a C++ compiler but establish coding standards for your novices that disallow the advanced features until they've been qualified to use them. Sort of like keeping an apprentice machinist away from the CNC machines. ;-) >I haven't noticed a big buildup of the code in C++ yet, but i look in the future for emerging problems from that direction. We have 2M flash memory and i want to have a lot of code... . In some situations one is very memory-limited, and it's easy for a language that's heap-oriented (C++, Java) to quickly consume all available memory. A poor template implementation can also eat ROM quickly. I'm working on a DSP-based project and DSPs typically get some of their bandwidth by getting code and data from limited on-chip memory. It's in such tight environments that a space-efficient compiler is critical. >>I don't see speed as a big issue, as one can always profile an app and >>recode the bandwidth pigs in hand-tuned assembler. Such code is likely >>to be a small part of any application. >a C++ routine call has overhead of 1 because it first get the value from the lookup table (get the correct function from the right father ) and then calls the function. Unless you use multiple inheritance, a virtual method lookup should take just a couple extra instructions (load vtable pointer, load method pointer, call indirect), and that should be insignificant unless it's in a critical loop. Indirect function calls are not uncommon in C, so I see C++ virtual methods as just a nicer syntax for something I'm already doing. >(one of the big pitfalls of C++, is calling a routine virtual in parent overloaded by child from constructor actually calls the father function instead of the child function) I think we've all been bitten by that one. Have your newbies keep an eye on the C++ newsgroups and you can watch other newbies make the mistakes first. ;-) >I wish we could have Java too, maybe it's just a dream, for sure for embedded a lot of code would have to be entered into the JVM (specific drivers), maybe there we will steal have to have the C++ (or C). That will depend on the specific application. I think Java is well-suited for GUI, and possibly for non-time-critical control flow. It also carries a lot of networking boilerplate, making TCP/IP apps simpler to code. For example, Java would be good for an instrument that has to return its results over the Internet (such as a remote weather station). For realtime apps, the Java garbage collector is the most scary thing, as it's likely to be non-deterministic in time. I don't see Java being used in an engine controller, for example. Java also lacks C++ destructor semantics that force a resource to be freed at the end of an object's scope. In Java one must explicitly free resources, which leaves yet another task for the programmer to forget to do. Kenneth Porter Systems Engineer Kensington Laboratories, Inc. 750 National Court Richmond, CA 94804-2008 Voice: 510-620-0235 FAX: 510-233-5544 mailto:kenneth_porter@kensingtonlabs.com http://www.kensingtonlabs.com
One of my bigger problems with using C++ in embedded projects is the way ctors are handled. When you have global class variables the compiler (in my case egcs) generates lots of constructor/destructor calls for them, where they are completely uneccessary. For example: struct general_thing { int weight; general_thing(int _weight = 0) : weight(_weight) {} virtual bool get() = 0; }; struct atom_bomb : public general_thing { long price; atom_bomb(long _price, int _weight = 1000) : price(_price), general_thing(_weight) {} virtual bool get(); }; const atom_bomb my_bomb(50, 100); I would like to have my_bomb somewhere in the ROM. And the example above should not generate any code as long as I don't call the constructors in another context. What happens is, that the compiler always generates a function for each source file that calls all the constructors and then generates a section that contains the pointer to that function. These sections from all files are then linked together into a table of function pointers and the init-functions of all global objects are called at program startup through this table. This is ok if my constructors are doing something other than just copying around values. This would cause in most situations just some overhead, but if you want to use ROM it's impossible to use (virtual) classes. Micha
On Mon, 24 Aug 1998 03:37:50 +0200, Michael Bruck wrote: >const atom_bomb my_bomb(50, 100); > >I would like to have my_bomb somewhere in the ROM. And the example above >should not generate any code as long as I don't call the constructors in >another context. What happens is, that the compiler always generates >a function for each source file that calls all the constructors and >then generates a section that contains the pointer to that function. >These sections from all files are then linked together into a table of >function pointers and the init-functions of all global objects are >called at program startup through this table. This is ok if my >constructors are doing something other than just copying around values. >This would cause in most situations just some overhead, >but if you want to use ROM it's impossible to use (virtual) classes. I doubt we'll see compilers soon that are clever enough to statically init an object with a vpointer and only scalar initializers in the ctor. 'Twould be nice, though! I recall looking up this question a few weeks ago (can't remember where) and I recall reading that the proper way to do this was to put things with static data in ROM'd POD structs and including an instance or reference to the struct in a small RAM-based class object. To hide the POD internal structure, declare it within the class: class Thing { struct ThingROMData { const int weight; }; const ThingROMData& data; Thing(const ThingROMData& _data) : data(_data) {}; public: static void InitThings(); // calls special ctor virtual bool get(); }; static const Thing::ThingROMData thing1data = { 100 }; // this gets ROM'd The actual machinery of Thing initialization will be application-specific, but this gives the basic idea of how to structure the ROM part of the data. In your example, since you want to parameterize the ctor, I'd suggest using a macro to perform the parameterization (since macros are expanded at compile time). I was going to suggest a template, but I can't see how to use a template to instantiate a class instead of creating a new type. Kenneth Porter Systems Engineer Kensington Laboratories, Inc. 750 National Court Richmond, CA 94804-2008 Voice: 510-620-0235 FAX: 510-233-5544 mailto:kenneth_porter@kensingtonlabs.com http://www.kensingtonlabs.com
> >I doubt we'll see compilers soon that are clever enough to statically >init an object with a vpointer and only scalar initializers in the >ctor. 'Twould be nice, though! I thinks it's not a question of the compiler. If you depend on the cleverness of the compiler to control the position of your data you would be unable to use this at all because: a) you don't know what the compiler on the other platform where you want to use your library too thinks about this, b) it's difficult to debug if you have to compile everything with -O100 c) I don't like this solution :) It would by better to be able to tell the compiler explitly what you want. It's not that this is a problem to implement in the compiler. F.e. in the following example I can't see any reason why the code should not work except that the standard defines the second line as invalid: struct { int a; } p = {1}; struct { int b; virtual f(); } q = {2}; If you think the {} syntax may be inappropriate for C++ and you would like the constructor syntax, then you could tell the compiler via e special keyword that the compiler is trivial in the sense that it yields only expressions that can be evaluted at compile-time. The question is whether the problem is worth to change the language or to implement a nonstandard keyword. > >I recall looking up this question a few weeks ago (can't remember >where) and I recall reading that the proper way to do this was to put >things with static data in ROM'd POD structs and including an instance >or reference to the struct in a small RAM-based class object. To hide >the POD internal structure, declare it within the class: > >class Thing { > struct ThingROMData { > const int weight; > }; > const ThingROMData& data; > Thing(const ThingROMData& _data) : data(_data) {}; >public: > static void InitThings(); // calls special ctor > virtual bool get(); >}; > >static const Thing::ThingROMData thing1data = { 100 }; // this gets >ROM'd You waste the space for the pointer (Thing::data). This is ok if you have big classes (many values). But if you have two or three bytes per class this is unacceptable. It also doesn't make your programs easier to read (ok, with a 40KB macro-header :) > >The actual machinery of Thing initialization will be >application-specific, but this gives the basic idea of how to structure >the ROM part of the data. > >In your example, since you want to parameterize the ctor, I'd suggest >using a macro to perform the parameterization (since macros are >expanded at compile time). I was going to suggest a template, but I >can't see how to use a template to instantiate a class instead of >creating a new type. Regarding templates I came to the same conclusion. Micha
On Tue, 25 Aug 1998 20:53:39 +0200, Michael Bruck wrote: >You waste the space for the pointer (Thing::data). This is ok >if you have big classes (many values). But if you have two or >three bytes per class this is unacceptable. It also doesn't >make your programs easier to read (ok, with a 40KB >macro-header :) Small classes with virtual methods just don't ROM effectively. Related question: Do compilers put the vtable in the text segment so that it can be ROM'd? The case where I was asking the question involved a big command table with fixed-size string buffers for each command and a series of flag bytes. I currently build this in assembler and use a C routine to scan the tables. Assembler is used because the tables have 26 internal labels to allow quick jumping to command entries starting with a specific character. (I inherited this design. In retrospect I could use 26 independent tables or use binary search, since the entries are of fixed size.) Obviously this is the kind of bulky data that could benefit from the architecture I described. Ken mailto:shiva@well.com http://www.well.com/user/shiva/ http://www.e-scrub.com/cgi-bin/wpoison/wpoison.cgi (Death to Spam!) Ken mailto:shiva@well.com http://www.well.com/user/shiva/ http://www.e-scrub.com/cgi-bin/wpoison/wpoison.cgi (Death to Spam!)
>On Tue, 25 Aug 1998 20:53:39 +0200, Michael Bruck wrote: > >>You waste the space for the pointer (Thing::data). This is ok >>if you have big classes (many values). But if you have two or >>three bytes per class this is unacceptable. It also doesn't >>make your programs easier to read (ok, with a 40KB >>macro-header :) > >Small classes with virtual methods just don't ROM effectively. Related Hey, that's not a solution! The point is that they don't ROM effectivly because the language designers didn't care about systems with limited resources. (do I need to explain this more detailed ?) And there are ways to easily change this. >question: Do compilers put the vtable in the text segment so that it >can be ROM'd? g++ puts them into .rodata. I think that's something that every compiler is able to do without any extra logic. But the probability that compiler XY puts vtables into .text/.rodata is the same as for global consts. > >The case where I was asking the question involved a big command table >with fixed-size string buffers for each command and a series of flag >bytes. I currently build this in assembler and use a C routine to scan >the tables. Assembler is used because the tables have 26 internal >labels to allow quick jumping to command entries starting with a >specific character. (I inherited this design. In retrospect I could use >26 independent tables or use binary search, since the entries are of >fixed size.) Obviously this is the kind of bulky data that could >benefit from the architecture I described. > Usually one decides to use C++ to make development easier (f.e. using the STL). But I don't know how to make my libraries more portable, the sources more readable and reduce the bugs when I use 50 lines of code just to wrap a struct that should go into ROM. In the case that you described above I can't see how you could use the new concepts that C++ offers. (classes, inheritance ... maybe some STL algorithms) In my case I wanted to make use of them and it's impossible because of some unimportant details. Micha