new does not always throw a badalloc exception if memory cannot be allocated
new does not always throw a badalloc exception if memory cannot be allocated
Hi,
I have asked Visual Micro
https://www.visualmicro.com/forums/YaBB ... 003983/0#0
why new does not always throw a badalloc exception if memory cannot be allocated. They recommended me to ask you.
Thanks
Richard
I have asked Visual Micro
https://www.visualmicro.com/forums/YaBB ... 003983/0#0
why new does not always throw a badalloc exception if memory cannot be allocated. They recommended me to ask you.
Thanks
Richard
Re: new does not always throw a badalloc exception if memory cannot be allocated
because we use compilation option: -fno-exceptions
See https://github.com/stm32duino/Arduino_C ... rm.txt#L71
Ref:
https://gcc.gnu.org/onlinedocs/libstdc+ ... tions.html
See https://github.com/stm32duino/Arduino_C ... rm.txt#L71
Ref:
https://gcc.gnu.org/onlinedocs/libstdc+ ... tions.html
Re: new does not always throw a badalloc exception if memory cannot be allocated
Since the C++ standard requires new to throw an exception if memory cannot be allocated, you should provide a version compiled with -fexception.
Without, functions relying on this will not behave as expected. For example
will not behave standard conforming at a memory allocation error.
Thanks
Richard
Without, functions relying on this will not behave as expected. For example
Code: Select all
std::vector<int> v;
int too_much_push_backs()
{
Serial.printf("Start too_much_push_backs() \n" );
while (true) // leave at an exception
{ // from push_back
v.push_back(1);
if (v.size() % 1000 == 0)
Serial.printf(" v.size()=%d \n", v.size());
}
}
Thanks
Richard
Re: new does not always throw a badalloc exception if memory cannot be allocated
there are still mcus with 4k memory around, there is no room for exceptions in those.
one can always edit the cflags in platform.txt and boards.txt locally if need be.
and malloc(), new etc are skeleton implementations
the stack can simply overwrite global variables with zero warning
let alone throw exceptions
microcontrollers are unlike cpu systems endowed with lots of memory and storage, with an os and specific hardware to manage that.
a 'well known' problem is use of complete desktop style libraries + exceptions will bloat the binary file quite a bit
https://miscsolutions.wordpress.com/201 ... -software/
for small mcus, they easily run out of flash or that your app / binary become 'too fat' to fit in flash while adding features / libraries.
if you are running on a chip with ample amount of memory and flash like 1 MB flash and like 512k sram and many megs of sdram and your app runs from sd ram. perhaps you could edit the flags in platform.txt locally to build a different binary.
add some good memory manager for malloc(), new etc and even run an os along with it.
one can always edit the cflags in platform.txt and boards.txt locally if need be.
and malloc(), new etc are skeleton implementations
the stack can simply overwrite global variables with zero warning
let alone throw exceptions
microcontrollers are unlike cpu systems endowed with lots of memory and storage, with an os and specific hardware to manage that.
a 'well known' problem is use of complete desktop style libraries + exceptions will bloat the binary file quite a bit
https://miscsolutions.wordpress.com/201 ... -software/
for small mcus, they easily run out of flash or that your app / binary become 'too fat' to fit in flash while adding features / libraries.
if you are running on a chip with ample amount of memory and flash like 1 MB flash and like 512k sram and many megs of sdram and your app runs from sd ram. perhaps you could edit the flags in platform.txt locally to build a different binary.
add some good memory manager for malloc(), new etc and even run an os along with it.
Re: new does not always throw a badalloc exception if memory cannot be allocated
Well, no compiled version is provided, only source. You build on your side and you can override yourself the compilation options thanks *.local files options from Arduino, see the Arduino platform specification for this.Richard wrote: Fri Jan 10, 2025 3:31 pm Since the C++ standard requires new to throw an exception if memory cannot be allocated, you should provide a version compiled with -fexception.
And @ag123 well explain the reasons for this.
Re: new does not always throw a badalloc exception if memory cannot be allocated
Thanks fpiSTM,
can you please tell me where I can find these *.local files for the Arduino IDE?
Are these the same files for the "Arduino IDE for Visual Studio 2022" extension from Visual Micro? If not, where can I find them?
Can I set these flags in the Arduino IDE or in the Visual Micro Extension?
Richard
can you please tell me where I can find these *.local files for the Arduino IDE?
Are these the same files for the "Arduino IDE for Visual Studio 2022" extension from Visual Micro? If not, where can I find them?
Can I set these flags in the Arduino IDE or in the Visual Micro Extension?
Richard
Re: new does not always throw a badalloc exception if memory cannot be allocated
You have to create it: https://arduino.github.io/arduino-cli/1 ... rmlocaltxt
Or modify the platform.txt.
I never used VS micro extension.
Or modify the platform.txt.
I never used VS micro extension.
Re: new does not always throw a badalloc exception if memory cannot be allocated
In the meantime I got the answer from the Visual Micro team
https://www.visualmicro.com/forums/YaBB ... 003983/0#2
Thanks a lot for all the answers. They were a great help.
Richard
https://www.visualmicro.com/forums/YaBB ... 003983/0#2
Thanks a lot for all the answers. They were a great help.
Richard
Re: new does not always throw a badalloc exception if memory cannot be allocated
Hi,
in my post from Fri Jan 10, 2025 9:34 pm I was too optimistic that I can solce the problem. Today I got
https://www.visualmicro.com/forums/YaBB ... 003983/0#0
from the VisualMicro team. That's why I have to come back to my posts and ask you again to change your build settings so that the -fexception switch in VisualMicro is passed to the compilation of the STM libraries.
I consider it a bug that after turning exception handling on, I get it only for a part of the code, with the final effect, that I don't get it at all for e.g. push_back.
There are many boards (e.g. the STM32 F303RE) with enough memory for exception handling. For such boards it should be possible to turn exception handling on. For an ESP32 with similiar memory it works this way.
A remark to your post by fpiSTM » Fri Jan 10, 2025 7:18 pm: After asking the VisualMicro team where I can set these flag (see the thread from above), I looked in boards.text and found that exception handling is already enabled:
compiler.cpp.flags={compiler.extra_flags} -c {compiler.optimization_flags} {compiler.warning_flags} -std={compiler.cpp.std} -ffunction-sections -fdata-sections -fno-threadsafe-statics --param max-inline-insns-single=500 -fno-rtti -fexceptions -fno-use-cxa-atexit -MMD {compiler.stm.extra_include}
Thanks
Richard
in my post from Fri Jan 10, 2025 9:34 pm I was too optimistic that I can solce the problem. Today I got
https://www.visualmicro.com/forums/YaBB ... 003983/0#0
from the VisualMicro team. That's why I have to come back to my posts and ask you again to change your build settings so that the -fexception switch in VisualMicro is passed to the compilation of the STM libraries.
I consider it a bug that after turning exception handling on, I get it only for a part of the code, with the final effect, that I don't get it at all for e.g. push_back.
There are many boards (e.g. the STM32 F303RE) with enough memory for exception handling. For such boards it should be possible to turn exception handling on. For an ESP32 with similiar memory it works this way.
A remark to your post by fpiSTM » Fri Jan 10, 2025 7:18 pm: After asking the VisualMicro team where I can set these flag (see the thread from above), I looked in boards.text and found that exception handling is already enabled:
compiler.cpp.flags={compiler.extra_flags} -c {compiler.optimization_flags} {compiler.warning_flags} -std={compiler.cpp.std} -ffunction-sections -fdata-sections -fno-threadsafe-statics --param max-inline-insns-single=500 -fno-rtti -fexceptions -fno-use-cxa-atexit -MMD {compiler.stm.extra_include}
Thanks
Richard
Re: new does not always throw a badalloc exception if memory cannot be allocated
No, you can override it using platform.local.txt.Richard wrote: Tue Jan 14, 2025 5:55 pm That's why I have to come back to my posts and ask you again to change your build settings so that the -fexception switch in VisualMicro is passed to the compilation of the STM libraries.
I never tested. It is common to simply disable it to save space. See below.Richard wrote: Tue Jan 14, 2025 5:55 pm I consider it a bug that after turning exception handling on, I get it only for a part of the code, with the final effect, that I don't get it at all for e.g. push_back.
Well, we feel free to contribute on this, it is a community project. Nothing prevent to enable it , choice is simply to save space using the Newlib nano by default (see below).Richard wrote: Tue Jan 14, 2025 5:55 pmThere are many boards (e.g. the STM32 F303RE) with enough memory for exception handling. For such boards it should be possible to turn exception handling on. For an ESP32 with similiar memory it works this way.
No, don't know how VSMicro handle build options but in the core, it is not enabled by default:Richard wrote: Tue Jan 14, 2025 5:55 pm A remark to your post by fpiSTM » Fri Jan 10, 2025 7:18 pm: After asking the VisualMicro team where I can set these flag (see the thread from above), I looked in boards.text and found that exception handling is already enabled:
compiler.cpp.flags={compiler.extra_flags} -c {compiler.optimization_flags} {compiler.warning_flags} -std={compiler.cpp.std} -ffunction-sections -fdata-sections -fno-threadsafe-statics --param max-inline-insns-single=500 -fno-rtti -fexceptions -fno-use-cxa-atexit -MMD {compiler.stm.extra_include}
https://github.com/stm32duino/Arduino_C ... 71C1-L72C1
Code: Select all
compiler.cpp.flags={compiler.extra_flags} -c {compiler.optimization_flags} {compiler.warning_flags} -std={compiler.cpp.std} -ffunction-sections -fdata-sections -fno-threadsafe-statics --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -fno-use-cxa-atexit -MMD {compiler.stm.extra_include}
https://github.com/stm32duino/Arduino_C ... ew.cpp#L27
It simply calls malloc which return null if not able to allocate memory...
I've tested the exception with your code (using platform.local.txt to override default config) and called manually:
Code: Select all
throw std::bad_alloc();
Doing this allows to get the catch as you expect.
Code:
Code: Select all
void setup() {
Serial.begin(9600);
}
void loop() {
int* p = new int;
delete p;
int n = 1;
int rep = 1;
Serial.println("\nStart N_Exception_Basics::test_too_much_news(mit_Exceptions) ");
#ifdef __cpp_exceptions
try {
#endif
while (p != nullptr) {
p = new int[n];
delete[] p;
n = n * 10;
rep++;
Serial.printf("n=%d p=%d \n", n, (int)p);
}
#ifdef __cpp_exceptions
throw std::bad_alloc();
} catch (std::exception& e) {
Serial.printf("Exception bei test_too_much_news n=%d what()=%s\n", n, e.what());
} catch (...) {
Serial.printf("... Exception bei test_too_much_news \n");
}
Serial.printf("nach catch ... Exception bei test_too_much_news \n");
#endif
}
Here sum up of space used depending of the config:Start N_Exception_Basics::test_too_much_news(mit_Exceptions)
n=10 p=536875600
n=100 p=536875600
n=1000 p=536875600
n=10000 p=536875600
n=100000 p=0
Exception bei test_too_much_news n=100000 what()=std::bad_alloc
nach catch ... Exception bei test_too_much_news
To sum up if you want exception support using Arduino IDE or cli (other ide, tools,... are not supported here):-fexceptions and Newlib standard
Sketch uses 100120 bytes (76%) of program storage space. Maximum is 131072 bytes.
Global variables use 3584 bytes (10%) of dynamic memory, leaving 29184 bytes for local variables. Maximum is 32768 bytes.
-fexceptions and Newlib nano
Sketch uses 33220 bytes (25%) of program storage space. Maximum is 131072 bytes.
Global variables use 1488 bytes (4%) of dynamic memory, leaving 31280 bytes for local variables. Maximum is 32768 bytes.
-fno-exceptions and Newlib nano
Sketch uses 23864 bytes (18%) of program storage space. Maximum is 131072 bytes.
Global variables use 1444 bytes (4%) of dynamic memory, leaving 31324 bytes for local variables. Maximum is 32768 bytes.
-fno-exceptions and Newlib standard
Sketch uses 99248 bytes (75%) of program storage space. Maximum is 131072 bytes.
Global variables use 3584 bytes (10%) of dynamic memory, leaving 29184 bytes for local variables. Maximum is 32768 bytes.
- override compiler.cpp.flags in a platform.local.txt to replace -fno-exceptions by -fexceptions
- use the Newlib standard.
And as stated before new return null if no space left but you can throw yourself the bad_alloc.