|
|
Home » U++ Library support » U++ Core » How to respond when memory is exceeded
How to respond when memory is exceeded [message #60976] |
Wed, 16 October 2024 09:41  |
 |
koldo
Messages: 3422 Registered: August 2008
|
Senior Veteran |
|
|
Hi all
Now, when you want to allocate a variable that is too large, the internal function calls Panic() and aborts the program. For the programmer, it is only possible to call InstallPanicMessageBox() first, so that just before closing the program, a defined function is called.
I wanted to ask you if it would be possible that in this case, the user function decides if the program stops or not. For example, imagine a design program that wants to open a file that is too big: instead of crashing the program, the PanicMessageBox() could do a throw with a warning that the file to be opened is too big, and the program would return to the previous state.
Best regards
Iñaki
|
|
|
|
|
|
|
|
|
|
|
Re: How to respond when memory is exceeded [message #61100 is a reply to message #61099] |
Mon, 18 November 2024 10:09   |
 |
koldo
Messages: 3422 Registered: August 2008
|
Senior Veteran |
|
|
Hello Mirek
This is a very simple test code to force the problem:
GUI_APP_MAIN
{
WithMain<TopWindow> dlg;
CtrlLayout(dlg, "Memory test");
dlg.butTest.WhenAction = []{
try {
Buffer<int> data;
data.Alloc(123456789012, 0);
PromptOK("Memory is alloc");
} catch (const std::bad_alloc& e) {
Exclamation("Caught bad_alloc");
}
};
dlg.Execute();
}

And this is the change in U++:
void OutOfMemoryPanic(size_t size)
{
throw std::bad_alloc();
/*char h[200];
snprintf(h, 200, "Out of memory!\nU++ allocated memory: %d KB", MemoryUsedKb());
Panic(h);*/
}
When pushing the button 5 times, no problem happens. Visually monitoring the Windows Task Manager, MemoryTest.exe seems to use the same memory all the time.
However, pushing the button one more time, MemoryLimitKb breached! Panic appears. It happens the same in debug and in release.
Best regards
Iñaki
|
|
|
Re: How to respond when memory is exceeded [message #61101 is a reply to message #61100] |
Mon, 18 November 2024 12:31   |
 |
mirek
Messages: 14206 Registered: November 2005
|
Ultimate Member |
|
|
koldo wrote on Mon, 18 November 2024 10:09Hello Mirek
This is a very simple test code to force the problem:
GUI_APP_MAIN
{
WithMain<TopWindow> dlg;
CtrlLayout(dlg, "Memory test");
dlg.butTest.WhenAction = []{
try {
Buffer<int> data;
data.Alloc(123456789012, 0);
PromptOK("Memory is alloc");
} catch (const std::bad_alloc& e) {
Exclamation("Caught bad_alloc");
}
};
dlg.Execute();
}

And this is the change in U++:
void OutOfMemoryPanic(size_t size)
{
throw std::bad_alloc();
/*char h[200];
snprintf(h, 200, "Out of memory!\nU++ allocated memory: %d KB", MemoryUsedKb());
Panic(h);*/
}
When pushing the button 5 times, no problem happens. Visually monitoring the Windows Task Manager, MemoryTest.exe seems to use the same memory all the time.
However, pushing the button one more time, MemoryLimitKb breached! Panic appears. It happens the same in debug and in release.
That is "buggy code" example. For something more real, try
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
GUI_APP_MAIN
{
TopWindow win;
win.Title("Testing");
win.WhenClose << [] {
try {
for(;;) {
byte *data = new byte[1024 * 4096];
for(int i = 0; i < 1024; i++)
data[i * 4096] = 1;
}
} catch (const std::bad_alloc&) {
Exclamation("Caught bad_alloc");
}
};
win.Run();
}
And try that in Linux...
That said, whatever, I think this really is totally futile, but I am going to change the code to actually throw bad_alloc, then catch it in main and do Panic there. I am NOT going to change the U++ code to work correctly in case bad_alloc is thrown, but maybe I will be able to compile some rules (like everything in try block has to be destructed). What a waste of time...
|
|
|
|
Re: How to respond when memory is exceeded [message #61110 is a reply to message #61101] |
Mon, 18 November 2024 19:36   |
 |
koldo
Messages: 3422 Registered: August 2008
|
Senior Veteran |
|
|
mirek wrote on Mon, 18 November 2024 12:31koldo wrote on Mon, 18 November 2024 10:09Hello Mirek
This is a very simple test code to force the problem:
GUI_APP_MAIN
{
WithMain<TopWindow> dlg;
CtrlLayout(dlg, "Memory test");
dlg.butTest.WhenAction = []{
try {
Buffer<int> data;
data.Alloc(123456789012, 0);
PromptOK("Memory is alloc");
} catch (const std::bad_alloc& e) {
Exclamation("Caught bad_alloc");
}
};
dlg.Execute();
}

And this is the change in U++:
void OutOfMemoryPanic(size_t size)
{
throw std::bad_alloc();
/*char h[200];
snprintf(h, 200, "Out of memory!\nU++ allocated memory: %d KB", MemoryUsedKb());
Panic(h);*/
}
When pushing the button 5 times, no problem happens. Visually monitoring the Windows Task Manager, MemoryTest.exe seems to use the same memory all the time.
However, pushing the button one more time, MemoryLimitKb breached! Panic appears. It happens the same in debug and in release.
That is "buggy code" example. For something more real, try
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
GUI_APP_MAIN
{
TopWindow win;
win.Title("Testing");
win.WhenClose << [] {
try {
for(;;) {
byte *data = new byte[1024 * 4096];
for(int i = 0; i < 1024; i++)
data[i * 4096] = 1;
}
} catch (const std::bad_alloc&) {
Exclamation("Caught bad_alloc");
}
};
win.Run();
}
And try that in Linux...
That said, whatever, I think this really is totally futile, but I am going to change the code to actually throw bad_alloc, then catch it in main and do Panic there. I am NOT going to change the U++ code to work correctly in case bad_alloc is thrown, but maybe I will be able to compile some rules (like everything in try block has to be destructed). What a waste of time...
Hi Mirek
I think that the for with allocs is really an example of bad code.
Imagine that you are doing a new Notepad++, and the user wants to open a file of, let's say, XXX Tb.
Two options:
a) Your Notepad++ would say "File too big", and will follow working normally.
b) Exclamation() dialog, and program closes
I prefer option a)
Best regards
Iñaki
|
|
|
Re: How to respond when memory is exceeded [message #61111 is a reply to message #61110] |
Mon, 18 November 2024 19:48   |
 |
mirek
Messages: 14206 Registered: November 2005
|
Ultimate Member |
|
|
koldo wrote on Mon, 18 November 2024 19:36mirek wrote on Mon, 18 November 2024 12:31koldo wrote on Mon, 18 November 2024 10:09Hello Mirek
This is a very simple test code to force the problem:
GUI_APP_MAIN
{
WithMain<TopWindow> dlg;
CtrlLayout(dlg, "Memory test");
dlg.butTest.WhenAction = []{
try {
Buffer<int> data;
data.Alloc(123456789012, 0);
PromptOK("Memory is alloc");
} catch (const std::bad_alloc& e) {
Exclamation("Caught bad_alloc");
}
};
dlg.Execute();
}

And this is the change in U++:
void OutOfMemoryPanic(size_t size)
{
throw std::bad_alloc();
/*char h[200];
snprintf(h, 200, "Out of memory!\nU++ allocated memory: %d KB", MemoryUsedKb());
Panic(h);*/
}
When pushing the button 5 times, no problem happens. Visually monitoring the Windows Task Manager, MemoryTest.exe seems to use the same memory all the time.
However, pushing the button one more time, MemoryLimitKb breached! Panic appears. It happens the same in debug and in release.
That is "buggy code" example. For something more real, try
#include <CtrlLib/CtrlLib.h>
using namespace Upp;
GUI_APP_MAIN
{
TopWindow win;
win.Title("Testing");
win.WhenClose << [] {
try {
for(;;) {
byte *data = new byte[1024 * 4096];
for(int i = 0; i < 1024; i++)
data[i * 4096] = 1;
}
} catch (const std::bad_alloc&) {
Exclamation("Caught bad_alloc");
}
};
win.Run();
}
And try that in Linux...
That said, whatever, I think this really is totally futile, but I am going to change the code to actually throw bad_alloc, then catch it in main and do Panic there. I am NOT going to change the U++ code to work correctly in case bad_alloc is thrown, but maybe I will be able to compile some rules (like everything in try block has to be destructed). What a waste of time...
Hi Mirek
I think that the for with allocs is really an example of bad code.
Imagine that you are doing a new Notepad++, and the user wants to open a file of, let's say, XXX Tb.
Two options:
a) Your Notepad++ would say "File too big", and will follow working normally.
b) Exclamation() dialog, and program closes
I prefer option a)
c) theide just views the file in read-only mode.
I prefer option c)
But really, notepad will need to allocate individual lines while loading, so the allocation pattern will look just like my example. Not like yours. Billions of small allocations until the memory is exhausted.
Mirek
|
|
|
|
Re: How to respond when memory is exceeded [message #61119 is a reply to message #61112] |
Tue, 19 November 2024 12:14  |
 |
mirek
Messages: 14206 Registered: November 2005
|
Ultimate Member |
|
|
So it is now implemented in "bad_alloc" branch. Basically, memory panic now throws bad_alloc which then caught in APP_MAIN to do normal Panic, so you can try and catch it.
Note that U++ code reaction to bad_alloc right now is
a) uncertain
b) likely and the ideal I will be striving upon, it is only safe to completely destruct U++ structures created in bad_alloc try block, there is no guarantee that any other operation works. Example:
VectorMap<String, String> map;
try {
map.Add("Hi", "there");
}
catch(std::bad_alloc) {}
is bad code. Instead you can use
VectorMap<String, String> map;
try {
VectorMap<String, String> map2;
map2.Add("Hi", "there");
map = pick(map);
}
catch(std::bad_alloc) {}
[Updated on: Tue, 19 November 2024 12:22] Report message to a moderator
|
|
|
Goto Forum:
Current Time: Mon Feb 17 20:52:24 CET 2025
Total time taken to generate the page: 0.05230 seconds
|
|
|