What shall we do?
The life of thousand people depends on that function you need to call, passing to it some fresh allocated memory. The operator new (unless the placement one is called) deals with OOM condition throwing a bad_alloc or returning a null-pointer in case the nothrow version of it is used.
But as programmer what can you do when a bad_alloc is thrown or a null-pointer is returned?
There are several options, but the most "nifty" one is the following.
When the operator new is not able to allocate the required memory it calls a function, at this point the function can try to free some memory, throwing an exception or exit the program. Exiting the program is not a good option I have to say, indeed the caller of the operator new (or operator new [] for the matter) expects a bad_alloc (or a derivation of it) or a nullptr (in case the nothrow was used).
A programmer is able to specify the function to be call in case of OOM with the following function:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
new_handler set_new_handler (new_handler new_p) noexcept; |
- Allocate a the programming startup a bunch of memory reserving it for future uses.
- Install the new handler that will free the reserved memory, in case the reserved memory was already release then throw bad_alloc.
The following code does exactly what described:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
class ReservedMemory { | |
public: | |
ReservedMemory() | |
: theMemoryReserved(new char[80000*1024]) | |
{} | |
~ReservedMemory() { delete []theMemoryReserved; } | |
void release() { | |
if (theMemoryReserved) { | |
std::cout << "FREEING SOME MEMORY" << std::endl; | |
delete []theMemoryReserved; | |
theMemoryReserved = nullptr; | |
} else { | |
std::cout << "NO MORE MEMORY TO FREE" << std::endl; | |
throw std::bad_alloc(); | |
} | |
} | |
private: | |
const char* theMemoryReserved; | |
}; | |
ReservedMemory rm; | |
int main(int argc, char** argv) { | |
std::set_new_handler([](){ rm.release(); }); | |
char * ptr = new char[50000*1024]; | |
std::cout << "SUCCEEDED" << std::endl; | |
char * ptra = new char[50000*1024]; | |
} |
issuing a ulimit -v 100000 before to run it (in order to decrease the memory that can be used), the output is the following:
FREEING SOME MEMORYSUCCEEDEDNO MORE MEMORY TO FREEterminate called after throwing an instance of 'std::bad_alloc'what(): std::bad_allocAborted (core dumped)
1 comment:
You explained this complex topic in a very simple way. Thank you for sharing.
C++ tutorial in urdu
Post a Comment