This has got to be an old, old topic by now, so please forgive for bringing this up again.
I wish to dynamically allocate some structures with a project I'm (still) working on. Yes, I know I can just "new xxx" them and this is all handled nicely for me but I really, really want to ring fence the memory available for this activity to control and monitor its use.
Reading and googling about I believe I can (or could) just do something like this to create the object:
Which all makes logical sense to me: effectively just peeling away some of the C++ coating enough to allow me to fiddle about under the hood (yes, aware of potential alignment issues).
However I get the following error from the IDE's compiler: error: invalid use of 'MyClass::MyClass' with the call to the class constructor.
Can anyone spare a moment to point me towards the right explanation document? I seem to be stuck in a bit of a bubble, all the answers I can find seem to fail for various reasons. I'm starting to pull my hair out, and I haven't got that much to spare!
Try a web search for "C++ placement new". But, it seem like more trouble than it's worth. You might just cause real problems while trying to solve the problem that doesn't exist.
I was never trained or used C++ (other than a trivial library in Arduino) but I created my own memory management code like that in standard C decades ago. I think you might be overthinking it.
class myClass {
int i;
};
int main () {
// get enough memory, say from the heap
void *p = malloc (sizeof (myClass));
// create a new instance in the memory allocated
myClass *q = new (p) myClass;
// call instance destructor (do not use delete in this case since delete would also call free)
q->~myClass ();
// free the memory being used
free (p);
return 0;
}
Since q points to the exactly the same place as p you can use only one pointer instead of two in your code.
class MyClass {
private:
int dummy;
public:
MyClass( void ) {
dummy = 1;
}
~MyClass() {
dummy = 0;
}
int Called( void ) {
return( dummy );
}
};
void *memory( size_t size ) {
return( malloc( size ));
}
void setup() {
Serial.begin( 9600 );
MyClass *ptr;
ptr = new( memory( sizeof( MyClass ))) MyClass;
Serial.print( ptr->Called());
}
void loop() {
// put your main code here, to run repeatedly:
}
And try to compile it, I get this:
/home/jeff/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -Wall -Wextra -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR -I/home/jeff/.arduino15/packages/arduino/hardware/avr/1.8.6/cores/arduino -I/home/jeff/.arduino15/packages/arduino/hardware/avr/1.8.6/variants/mega /home/jeff/.cache/arduino/sketches/7E3466A6CFA5C01F481E628463A906F1/sketch/sketch_feb16a.ino.cpp -o /home/jeff/.cache/arduino/sketches/7E3466A6CFA5C01F481E628463A906F1/sketch/sketch_feb16a.ino.cpp.o
/tmp/.arduinoIDE-unsaved2025116-96128-1961pf8.pk7q/sketch_feb16a/sketch_feb16a.ino: In function 'void setup()':
/tmp/.arduinoIDE-unsaved2025116-96128-1961pf8.pk7q/sketch_feb16a/sketch_feb16a.ino:26:42: error: no matching function for call to 'operator new(sizetype, void*)'
ptr = new( memory( sizeof( MyClass ))) MyClass;
^~~~~~~
<built-in>: note: candidate: void* operator new(unsigned int)
<built-in>: note: candidate expects 1 argument, 2 provided
exit status 1
Compilation error: no matching function for call to 'operator new(sizetype, void*)'
Yes, tried this already, hence my confusion.
The things I thought ought to work, and the things I've found (so far) which say they ought to work, don't. I don't think I'm being that silly - though it is always a possibility.
I have good reasons for wishing to directly manage the heap: memory is tight so I wish to statically allocate the heap space to enforce a hard limit on what's available. I'd rather the software has to manage an allocation failure than start allocating structures into the space required by the stack.
I'm still trying (to paraphrase an old saying) to get a quart into a pint pot. Literally every byte matters.
It seems that you are using an AVR board. I'm using ESP32 which uses C++ 201703 and the code compiles without a problem. Can you Serial.print __cplusplus to check C++ version you are using?
Thank you - an almost throw away comment on a web page somewhere else said "if you're using something older than 17 you only need do this" (redefine the new and delete operators). As normal, once seeing the actual answer, it all seems so easy combined with a wave of "why didn't I see that before?".
It's either too late here or it's time I started thinking about another hobby.