Is object orientation bad for embedded systems, and why? [closed]
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this questionMany embedded engineers use c++, but some argue it's bad because it's "object oriented"?
Is it true that being object oriented makes it bad for embedded systems, and if so, why is that really the case?
Edit: Here's a quick reference for those who asked:
so we prefer people not to use divide ..., malloc ..., or other objec开发者_如何学Got oriented practice that carry large penalty.
I guess the question is are objects considered heavyweight in the context of an embedded system? Some of the answers here suggest they are and some suggest they're not.
Whilst I'm not sure it answers your question, I can summarise the reasons my previous companies source code was pure C.
It's firstly worth summarising the situation:
- we wanted to write a large amount of "core" code that would be highly portable across a large number of ARM embedded systems (mostly mid-range mobile phones; both smart phones and ones running RTOSs of various ages)
- the platforms generally had a workable C compiler, though some for example didn't support floating point "double"s.
- in some cases the platform had a reasonable implementation of the standard library, but in many cases it didn't.
- a C++ compiler was not available on most platforms, and where it was available support for the C++ standard library, STL or exceptions was highly variable.
- debuggers often weren't available (a serial port you could send debug printfs to was considered a luxury)
- we always had access to a reasonable amount of memory, but often not to a reasonable malloc() implementation
Given that, we worked entirely in C, and even then only a restricted set of C 89. The resulting code was highly portable. We often used object orientated concepts though.
These days "embedded" is a very wide definition. It covers everything from 8 bit microprocessors with no RAM or C compilers upto what are essentially high end PCs (albeit not running Microsoft Windows) - I don't know where your project/company sits in that range.
Taking your quote at face value, dynamic memory allocation is completely separate concept from object-oriented software design, so it's outright false. You can have object-oriented design, and not use dynamic memory allocation.
In fact, you can do OO in C to an extent (that's what Linux kernel does). The real reason that many embedded developers don't like C++ is that it's very complex and it is hard to write straight-forward and predictable code in it. Linus has a good recent rant on why he does not like C++ (it's better and more reasoned than his old one, I promise). Probably most folks just don't articulate it very well.
What makes you say that C++ is Object Oriented? C++ is multiparadigm, and not all of the features that C++ provides are useful for the embedded market due to their overheads. (So... Just don't use those features! Problem solved!)
Object Oriented is great for embedded systems. It focuses a lot on encapsulation, data hiding, and code sharing. One can have Object Oriented embedded systems without division or dynamic memory allocation.
Division and dynamic memory allocation are enemies of embedded systems regardless of Object Oriented, Data Oriented or procedural programming. These concepts may or may not be used in the implementation of Object Oriented designs.
Object Oriented allows for a UART class to transmit instances of Message objects without knowing the content of the Message objects. A Message could be the base class and have several descendant classes.
The C++ language helps promote safe coding in embedded systems by allowing constructors, copy constructors, and destructors, which would only remembered in the highest disciplined C language embedded systems.
Exception handling is also a pain to get working in the C language. The C++ provides better facilities embedded into the language.
The C++ language provides templates for writing common code to handle different data types. A classic example is a ring buffer or circular queue. In the C language, one would have to use "pointers to void" so that any object could be passed. C++ offers a template so one can write a Circular_Queue class that works with different data types and has better compile-time type checking.
Inheritance allows for better code sharing. The shared code is factored into a base class and child classes can be created that share the same functionality; through inheritance.
The C language profides function pointers. The C++ languages provides facilities for function objects (function pointers with attributes).
Sorry, I just don't like those people who limit embedded systems to C language because of rumors and little knowledge and experience with C++.
Object-oriented design by itself isn't bad. The answer lies in your quote. Especially in real-time embedded systems, you want to make your code as light and efficient as possible. The things mentioned in your quote (objects, division, dynamic memory allocation) are relatively heavyweight and can usually be replaced with simpler alternatives (for eg. using bit-manipulation to approximate division, allocating memory on the stack or with static pools) to improve performance in time-critical systems.
Nothing about 'object-oriented' is bad for embedded systems. OO is just a way of thinking about software.
What's bad for embedded systems is that, in general, they have less sophisticated debuggers, and C++ does a lot of crazy stuff 'behind your back', so to speak. Those pieces of hard-to-get-access-to code will drive you nuts.
C++ was designed with the philosophy of don't pay for what you don't use. So apart from the lack of good embedded compilers, there's no real reason.
Maybe CFront could have compiled C++ into C, which has a myriad of compilers...
Edit: The Comeau compiler transforms C++ into plain C, so the no-compiler argument doesn't hold.
As others have noted, 'embedded' encompasses a broad and varied range of hardware/software options. But...
The quote you give will give microcontroller embedded types shivers. Dynamic allocation is a no-no, if you have an error, you crash the system in unpredictable ways. Divides are heavily discouraged since they take forever in execution time. Objects are only discouraged insofar as they tend to carry lot's of 'stuff' around with them, all that 'stuff' takes up space, and microcontrollers don't have any.
I think of embedded as being projects that are small and specific, you don't worry much about extensibility or portability. You write clean code in C that does only and exactly what you want your device to do, reliably. You choose one chip family so you can move your (almost the) same code among different hardware options with minor tweaks to the port your writing too or initialization of configuration fuses.
So, you don't need to define
- 4 wheeled Transportation
- Car
- Toyota
Since you're only working on Toyotas. And the difference in accelerations between a Camry and Corolla are stored as constants in a register.
As said above, it's what object-oriented / malloc / math do behind your back that carries a penalty - both in code size and CPU cycles which are usually in short supply in embedded.
As an example, including the sqrt() function in a loop added so much overhead in recursive calculations that we had to remove it and work a fast approximation around it, using a lookup table if I remember correctly.
By all means use any tools/langauges you like, but you need to at least be able to lift the lid and check just how much extra code is being generated behind your back.
Programming is always about using the right tool for the job. There are no pat answers, and that is especially true in the embedded world. If you want to become skilled in embedded development you will be just as intimately familier with C as you are with C++.
First, let's pick this apart:
so we prefer people not to use divide ..., malloc ..., or other object oriented practice that carry large penalty.
Division and malloc
are not unique to object oriented programming, they are present in procedural languages too (and presumably functional, and whatever other paradigms you might think of).
Division and malloc
can be a problem on an embedded system if the system has sufficiently limited resources, that much is true, but they will be a problem no matter what programming paradigm you use.
Onto the main issue "Is object orientation bad for embedded systems?".
Firstly, 'object orientation' is quite a broad spectrum. Some people have conflicting ideas about what it actually means. There's a minimalist definition where an object is essentially just a bundle of functions (or 'methods') and data, and there's a more 'purist' definition that also includes features like inheritance and polymorphism.
If you take the minimalist definition of OOP then no - OOP is not bad for embedded systems. It does depend on the language, but it's entirely possible for using objects to be just as cheap as not using objects (and possibly cheaper in some situations). In C++, an object (without virtual
methods, which I'll get to in a moment) takes up no more memory than its individual fields would if they weren't part of an object. In C++, (the size of) an object is equal to the sum of (the size of) its parts.
However, if you take the 'puritan' view of OOP and insist on including inheritance and polymorphism then the answer is 'yes, it is bad'. Inheritance is perhaps less of a concern (depending on the language), but polymorphism via virtual
methods is a definite memory chewer. virtual
functions are usually implemented by maintaining a 'vtable' (a virtual method table) that stores pointers to the correct functions, and each object must store a pointer to its vtable to enable dynamic dispatch (the process of calling virtual functions) to work properly. There are circumstances in which inheritance can use more memory than solutions that don't require inheritance - typically when comparing inheritance to composition, composition sometimes uses less memory.
One last point, particularly for the case of C++ (since that's usually what people mean when they talk about using OOP on embedded systems). People often say that "C++ does strange things behind your back" - it does do some things without those things being immediately obvious when looking at the code, such as producing the vtables I mentioned earlier, however it doesn't do these things "behind your back" in an attempt to thwart you, it does these things because they are simply needed to implement the features being used. Overall there are very few detrimental things that happen 'behind the scenes', and the things it does aren't exactly arcane or mysterious, they're generally quite well known and they're things the programmer ought to be aware of when programming for an embedded system. If you don't know about them then you don't know your tools properly and you should research them some more.
Having said all that, remember that people are free to be selective with which language features they do and don't use. It makes absolute sense to avoid the more expensive features like virtual functions, but it doesn't make sense to forgo an entire language (like C++) simply because it has a few expensive entirely optional features (like virtual functions) - that's just throwing the baby out with the bathwater.
精彩评论