-2

In the context of embedded software I want to make a std::vector-like container. Vector has both size and capacity, which means vector has allocated capacity*sizeof(T) bytes, but only size entries are constructed. An example

vector<string> v;
v.reserve(100)
v.resize(10)

v[9] gives a valid string , but v[10] gives a valid allocated memory portion of uninitialized data, so any string method will have an undefined behaviour, like v[10]= string(), if string& operator(const string& rhs) tries to destroy *this.

How can I build an object in a given memory address just using C++ compiler without including <new> or any other C++ standard include files?

UPDATE Can I write a custom implementation of placement new operator and make final executable independant from libstdc++.so? I don't want static linking against libstdc++.a either.

R. F. Luis
  • 99
  • 2
  • 7
  • 3
    use `std::array` when dynamic allocations are out – 463035818_is_not_an_ai Mar 14 '22 at 11:09
  • 2
    And note that `std::string` already implies the use of `new`. – πάντα ῥεῖ Mar 14 '22 at 11:24
  • You seem to be looking for *placement new*: `new (pointerToCorrectlyAlignedMemory) WhateverType(/*constructor arguments*/)`. – Aconcagua Mar 14 '22 at 11:33
  • By the way: If you do rely on dynamic memory allocation anyway then what's the point of not using `std::vector`? Apart from, it's possible to provide the vector a custom allocator implemented to better fit your personal needs. Maybe that's an option, too. – Aconcagua Mar 14 '22 at 11:43
  • It's trivial to check if an index is valid i.e. before accessing `v[i]` check if `i` is between `0` and `v.size()-1` inclusive. It is also trivial to place the vector as a member of another class, and have all operations on that class (e.g. `operator[]()`) check and resize the vector as needed before accessing an element. You can also ensure that resizing does not change `v.capacity()` if you wish, by not resizing if an index exceeds `v.capacity()-1` (and, optionally, letting the caller know - such as by throwing an exception). – Peter Mar 14 '22 at 13:20
  • So just include `` specifically? – Nathan Pierson Mar 14 '22 at 14:38
  • I can use dynamic memory, but I don't want to include all the C++ standard library. The point is using C++ as language to use OOP, function overloading and templates but at the end, linking with C standard library. I use string and vector as an example, but I didn't mean std::string. I saw examples of [vector valid for POD](https://www.codespeedy.com/using-vector-class-without-header-file-in-cpp/), but non-suitable for alive objects, like a string (whatever implementation). – R. F. Luis Mar 14 '22 at 14:40
  • Using placement new implies including ``. I need to call the constructor on a given memory address. Container must allocate/release memory and constructing/destroying the objects inside. – R. F. Luis Mar 14 '22 at 14:49
  • Does this answer help: https://stackoverflow.com/questions/519808/how-to-call-a-constructor-on-an-already-allocated-memory. I have no idea if you can actually get C++ to work without including the std library, though. – Joseph Larson Mar 14 '22 at 14:55
  • In the context of embedded systems, you *do not want* to use dynamic memory. Search the internet for "memory fragmentation". Many embedded systems allocate a static array rather than using dynamic memory. Can your embedded system afford running out of memory due to fragmentation or afford the time for garbage collection? – Thomas Matthews Mar 14 '22 at 15:41
  • I do not understand. `without including ` it's text. Copy the text from the file `new` into your code. Remove the parts you do not need. `Can I write a custom implementation` You "can" do anything, write your own compiler. You can write your own libstdc++.so. – KamilCuk Mar 17 '22 at 09:56
  • 1
    You'll save yourself from a whole lot of bloat and headache if you simply switch to C as early on as possible. You can still have OO, the main real difference between C and C++ is the lack of RAII, but that's mildly useful in embedded systems anyhow. I'd say that the trend overall in embedded systems since C++11 is to abandon C++. It was never particularly suitable for embedded systems, but it has gone from merely problematic to actively harmful. I could rant forever about the use of `auto` alone. – Lundin Mar 17 '22 at 10:30

1 Answers1

0

How can I build an object in a given memory address just using C++ compiler without including or any other C++ standard include files?

You have to read your compiler documentation and/or source code and related libraries and find out what is needed for that particular compiler with particular options used by you to allow this particular compiler with this particular configuration to work with placement new. I.e. if you can't use portability features like header files, you have to provide the compiler with your own non-portable replacement of header files.

For example, the following should be fine for gcc x86_64:

inline void* operator new(unsigned long, void* __p) { return __p; }
inline void operator delete(void*, void*) { }

struct A {};
int main() {
    alignas(A) char buf[sizeof(A)];
    struct A *a = new (buf) A;
    a->~A();
    ::operator delete(buf, a);
}

make final executable independant from libstdc++.so?

In the same way, compiling against LLVM libc++ makes the executable independent of GNU libstdc++. Provide your own implementation of needed functions in libstdc++ and link with them.

Placement new are inline empty functions on gcc. They use no symbols from the shared library.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • 1
    Rather, for an embedded system you'll want to do something along the lines of this [C example](https://stackoverflow.com/a/70667901/584518) using a simple memory pool in .bss rather than the stack. Swap out the `static_alloc` function for `operator new[]`, pretty much. And in C++ there's no need to pass a function along either. – Lundin Mar 17 '22 at 10:38