How can you do C ++ when your built-in compiler does not have operator support or STL?

I am working on a senior group project for my university, and I encountered a serious obstacle in trying to get my code to work.

The compiler that we have for our Atmel 8-bit microcontroller does not support new or remote operators, and it does not support C ++ STL. I could program it in C, but I need to implement the A * algorithm, which I have never done before. Although I tried C first, I soon realized that I had never done pure C. Trying to model objects using structures and functions slows me down, since I'm so used to the strong C ++ syntax.

Despite this, the exact wording of my compiler flaws can be found here: http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_cplusplus

To overcome them and use C ++, I considered the following possibilities. 1) Do not allocate anything, just use templates to create fixed arrays on the stack. 2) Select and find the hack to call the constructor for objects, as soon as I allocated space for them. Placing a new one is not an option since the new one is not an operator. 3) Just use C and dry it, its microcontroller, why am I getting fantasy? 4) Find the best compiler that is likely to cost $$$.

The second option is the most difficult, but it will have the largest payback in terms of how I can write this code. However, I believe that debugging can be a huge pain if I am wrong. I am thinking of creating objects on the stack, copying their bits into the allocated space, and then nulling the bits in the object so that it does not call its destructor. To do this, I would access the bits directly using the unsigned pointer char and the sizeof operator to get the byte.

It sounds awful and I don’t know if it can work reliably, but I’m considering it. I know that vtables can be a problem, but I do not intend to use any vtables, since this is just an 8-bit microcontroller.

+6
c ++ c memory-management embedded microcontroller
source share
8 answers

For write-only purposes, zeroing bits in an object will not affect the invocation of the calling destructor (unless the compiler has a special quirk that allows this behavior). Just write some registry statements in your destructor to verify this.

Structuring your program so as not to highlight anything is probably a way to develop a system. I didn’t work with embedded systems before, however I read some experienced built-in stores that prevent the use of dynamic memory, because the runtime has its drawbacks.


However, if necessary, you can still use the new placement. If you don't have a <new> header, here are the relevant lines directly from it in my version of GCC:

 // Default placement versions of operator new. inline void* operator new(std::size_t, void* __p) throw() { return __p; } inline void* operator new[](std::size_t, void* __p) throw() { return __p; } // Default placement versions of operator delete. inline void operator delete (void*, void*) throw() { } inline void operator delete[](void*, void*) throw() { } 

Stick to something somewhere in the header file included in every source file that uses the new / delete location.

An example of a file that checks this:

 #include <cstdio> #include <new> int main(int argc, char** argv) { typedef char const* cstr; char foobar[16]; cstr* str = new (&foobar) cstr(argc > 1 ? argv[1] : "Hello, world!"); std::puts(*str); str->~cstr(); } 

In my version of GCC, this does not use libstdc++ (if -fno-exceptions ).


Now, if you want to combine this with malloc (if your platform provides this), you can do this:

 #include <cstdio> #include <cstdlib> inline void* operator new (std::size_t n) {return std::malloc(n);} inline void* operator new[](std::size_t n) {return std::malloc(n);} inline void operator delete (void* p) {std::free(p);} inline void operator delete[](void* p) {std::free(p);} int main(int argc, char** argv) { typedef char const* cstr; cstr* str = new cstr(argc > 1 ? argv[1] : "Hello, world!"); std::puts(*str); delete str; } 

This allows you to use the standard new / delete that you are familiar with without using libstdc++ .

Good luck

+10
source share

Do not fight with your tools. If the only compiler you have for your embedded system is the C compiler, learn C - it's not complicated. Trying to create some sloppy version of the two languages, just to solve a fairly simple programming problem will end in tears.

To look at it differently, if your embedded platform does not even support the C compiler, but only assembler, will your first impulse sit and write the C ++ compiler in assembler? I hope not, I hope you sit down instead and learn how to use assembler to complete your task - writing a C ++ compiler (or even a C compiler) will be completely inappropriate use of your time and will almost certainly lead to a crash.

+23
source share

I think that you are approaching the problem from a point of view that is less than optimal.

You focus on the compiler (or lack thereof), instead of focusing on hardware.

The most likely answer to your main questions is "because the hardware does not support all of these materials in C ++." Embedded hardware (microcontrollers) are marked for hardware configuration - memory cards, interrupt handlers, I / O, etc.

In my opinion, you should FIRST spend some time with the hardware book for the microcontroller, having studied all the devices and devices, that is, how it was designed and for what main purpose. Some of them were designed for quick memory manipulation, some for fast I / O processing, some for A / D type operation, some for signal processing. The type of microcontroller dictates the assembler instructions that they wrote for it, and this dictates what any higher level compiler can do.

If this is important, spend a little time on the assembler - it will tell you what designers consider important. He will also tell you a lot about how much you can get from a high-level compiler.

As a rule, microcontrollers do not support C ++, because the design really does not care about objects or fancy memory processing (from the point of view of C ++). This can be done, but you often try to crop a circular snap in a square hole to get constructors and destructors (both "new" and "delete") to work in a micro environment.

IF you have a C compiler for this device, consider it a blessing. A good C compiler is often "more than enough" to create great firmware.

Greetings

-Richard

+6
source share

Just because it does not have these tools does not mean that you cannot use C ++. If the project is large enough, access to an object-oriented design can be reasonably motivated.

If it does not support "new", then this is probably because it makes no sense to make an automatic distinction between the heap and the stack. This may be due to your memory configuration. This may also be due to the fact that memory resources are so limited that very careful allocation makes sense. If you absolutely need to implement your own “new” operator, you can consider adapting Doug Lea malloc . I believe that he started his dispenser in a similar case (overriding C ++ new).

I like STL, but without it you can still do useful things. Depending on the size of the project, you might be better off using an array.

+4
source share

I had a similar compiler that implemented a fancy version of Embedded-C ++ standard . We had an operator new that would call constructors for us, and in most cases, call destructors. The compiler / runtime provider went through and implemented try and catch using setjmp and longjmp as a convenience to the engineer. The problem was that they never mentioned that throw would not call local object destructors!

In any case, our group inherited the code base after someone wrote an application that works as it did in the C ++ standard: using RAII methods and all other goodness. We ended up rewriting it with what some of us call object-oriented C. Perhaps you should consider just biting a bullet and writing in direct C. Instead of constructors, there is an explicitly called initialization method. Destructors become explicitly called the termination method. There is not much C ++ that you cannot simulate in C quite quickly. Yes, MI is a pain in ... but one inheritance is pretty simple. Take a look at this pdf for some ideas. It almost describes the approach we took. I am very sorry that I have not written our method anywhere ...

+2
source share

You can find useful code on my A * training site . Although the code I wrote to support this use, STL should be easy to strip support for STL. In addition, it includes a pool allocator (fsa.h), which I wrote to speed up STL on game consoles. This is C ++ code, but I have ported it from C, and I don’t think it would be difficult to do it differently. The code has been verified by more than 10,000 people, so it is a good base to start.

Replacing the STL structures that I use is not a problem, as it is limited to Vectors. I use one of the vectors as a priority queue using heap functions (make_heap and push_heap). You can replace this with the old old C code , which has a priority queue implemented in C that should just go into your code. (Which only highlights, so you can replace it with a pointer to a reserved area of ​​your memory.

As you can see in this code snippet from the header, the main difference in C code is that there is no this pointer, there is no object, so your code usually takes an object pointer as the first argument.

 void PQueueInitialise( PQUEUE *pq, int32 MaxElements, uint32 MaxRating, bool32 bIsAscending ); void PQueueFree( PQUEUE *pq ); int8 PQueuePush( PQUEUE *pq, void *item, uint32 (*PGetRating) ( void * ) ); int32 PQueueIsFull( PQUEUE *pq ); int32 PQueueIsEmpty( PQUEUE *pq ); void *PQueuePop( PQUEUE *pq, uint32 (*PGetRating) ( void * ) ); 
+1
source share

Why not write it first on your desktop computer, given the limitations of the compiler, debug it, make sure it works fine, and only then move to the embedded environment?

0
source share

when I was doing the built-in work, I couldn’t even associate the C runtime with memory limitations, but the hardware had a DMA (dynamic memory allocator) instruction, so I wrote my own malloc with this equipment, your equipment probably has similar, so you can write malloc and then a new one based on malloc.

In any case, in the end I used 99% stack allocation, and a few restrictions set the static objects that I will recycle by creating in place. This may be a good solution.

0
source share

All Articles