0

Im writing embedded code that cannot use memory allocation! Also, static objects (therefore constructed before the microcontroller has executed the main funtion with all its initialization) shall be constructed within the main after the initialization, not before.

The only solution people suggest is to use static object pointers and allocate (construct them with new) during initialization. since this is no option for me, is there no other solution?

what i wanna do is as follows:

class A
{
public:
  A(int a, bool b)
  : myVal1(a), myVal2(b)
  {

  }
private:
  int myVal1;
  bool myVal2;
}

class B
{
public:
  B(char x)
  : myChar1(x) // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
  {

  }

  void init()
  {
    // now i wanna construct myObjectA
    myObjectA(123, false);
  }
private:
  char myChar1;
  A myObjectA; // <-- NO CONSTRUCTION, NO PARAMETER
}

static B myObjectB('F'); // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA

void global_init()
{
// ... do before construction      

  // now i wanna construct myObjectA
  myObjectB.init();

  //... do after construction
}
  • 3
    Construction is not memory allocation. Things get constructed all the time, without memory allocation. So, what exactly is the problem with placement new? – Sam Varshavchik Sep 12 '17 at 19:29
  • 3
    https://en.wikipedia.org/wiki/Placement_syntax – Solomon Slow Sep 12 '17 at 19:30
  • 1
    `new` operator does not have to allocate memory. You can use it on a preallocated piece of memory as well, see [placement new](https://stackoverflow.com/questions/222557/what-uses-are-there-for-placement-new). So all you have to do is take some memory from the stack (as a char array of expected size) and use placement new on the reference. – freakish Sep 12 '17 at 19:31
  • Why doesn't `int main() { B myObject('F'); .... }` work? – alain Sep 12 '17 at 19:31
  • .. you can get a pointer to it, it lives as long as main? – alain Sep 12 '17 at 19:32
  • Use static pointers, and have main assign the addresses of objects to them like in alain's comment. – StoryTeller - Unslander Monica Sep 12 '17 at 19:33
  • You must have run-time support code somewhere that calls your `main()`, right? (back in C days, we used to call it `crt0`. I don't know what it's called today.) Why does it not initialize static objects? Can you modify it to initialize static objects? – Solomon Slow Sep 12 '17 at 19:34
  • 2
    You have an issue with terminology. "cannot use memory allocation" - I guess this means you can not use stock dynamic memory allocation (no `new` or `malloc`). "within the main" - I guess this means allocating on the stack (which may not be available as well). It still involves memory allocation. If you have an object instance then at least some form of memory allocation happened. So it looks like you are looking for a way to reserve some memory for it at static storage and then to manually call a constructor. – user7860670 Sep 12 '17 at 19:34

2 Answers2

0

Do you have boost available?

#include <boost/optional.hpp>

class A
{
public:
  A(int a, bool b)
  : myVal1(a), myVal2(b)
  {

  }
private:
  int myVal1;
  bool myVal2;
};

class B
{
public:
  B(char x)
  : myChar1(x) // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA
  {

  }

  A& getA() {
      assert(myObjectA);
      return myObjectA.get();
  }

  void init()
  {
    // now i wanna construct myObjectA
    myObjectA.emplace(123, false);
  }
private:
  char myChar1;
  boost::optional<A> myObjectA; // <-- NO CONSTRUCTION, NO PARAMETER
};

static B myObjectB('F'); // <-- NO CONSTRUCTION, NO PARAMETER OF MYOBJECTA

void global_init()
{
// ... do before construction      

  // now i wanna construct myObjectA
  myObjectB.init();

  //... do after construction
}

int main()
{
    global_init();
}
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
  • thank you for your reply. no, i am developping an embedded os for microcontrollers with very low footprint. there is almost no feature of c++ im able to use since all nice features use too much RAM. what im doing here is basically writing C89 code with the ability of classes and namespaces, so i would call it limited-embedded-c++. (Eg: the feature "list" of c++ is really cool, just so heavy, so i use basic versions of a fifo or mostly the rtos feature queue (thread save) are used instead) –  Sep 13 '17 at 16:32
  • @lunoname I understand. I used to do the same in C. one platform had 2k of ram for everything. program stack, interrupt stack and globals. No possibility of a heap. – Richard Hodges Sep 13 '17 at 16:35
  • hehe yeah. well i could use heap but the criteria here is no-failure-allowed, with pure static allocation i know at compile time it will never fail to allocate (given all rtos stacks are big enough :) ) –  Sep 13 '17 at 19:12
0

You can use a storage area large enough to create there an instance of A and placement new to control the time you create it.
As an example:

#include #include

struct A {
    A(int a, bool b): myVal1(a), myVal2(b) {}

    void foo() {}

private:
    int myVal1;
    bool myVal2;
};

struct B {
    B(char x): myChar1(x) {}
    ~B() { if(ptr) { ptr->~A(); } }

    void init() {
        ptr = new (&storage) A{123, false};
    }

    A * myObjectA() {
        return ptr;
    }

private:
    char myChar1;
    std::aligned_storage_t<sizeof(A), alignof(A)> storage;
    A *ptr{nullptr};
};

static B myObjectB('F');

void global_init() {
    // ... do before construction      

    // now i wanna construct myObjectA
    myObjectB.init();

    //... do after construction
}

int main() {
    global_init();
    myObjectB.myObjectA()->foo();
}

This won't allocate memory (if I got right what you mean for that) and the instance of A is actually created within B::init (that seems to be a requirement from what you wrote in your question).


If you have access to a compiler that supports C++17 or you can use the C++ Boost Libraries, std::optional is a valid alternative as suggested in another answer. Anyway you didn't specify the revision of the standard to which to adhere, so... Here is a way to go in any case.

skypjack
  • 49,335
  • 19
  • 95
  • 187
  • The `storage` could lack required alignment. I'd suggest adding `alignas()` or even better using `std::aligned_storage_t` instead of a plain char array. – HolyBlackCat Sep 12 '17 at 21:50
  • @HolyBlackCat I kept the example as simple as possible, but you're right. Pretty important a detail. Answer updated. – skypjack Sep 13 '17 at 05:07
  • @skypjack yes! this was the solution i was looking for! allocate storage in memory for the object statically. then, whenever i want, i can acutally construct it... one question here, why do you use structs instead of a class? –  Sep 13 '17 at 16:32
  • @lunoname They are both classes. Default visibility changes. That's all. It's a matter of taste mainly. – skypjack Sep 13 '17 at 16:47