My list of options is as follows:
In everyday (non-critical) situations, aborting the program due to lack of memory is what you can do yourself (preferably recording in a log). On cell phones that's exactly what happens. If the operating system does overcommiting (say it has been allocated successfully but only allocates memory when it is actually used), it will not be a good idea to test the return of malloc (in C) or capture the new exception (in C ++) so you're really screwed .
If your application has a main "waiting for user commands" loop (since it is a GTK + application) and some well defined start and finish operations that can allocate a lot of memory, you could catch the exception in the main loop and warn the user that the operation failed. Probably on returning to the main loop you should already have some memory released (the destructors have run). You can also warn in the message that the program may have become unstable and suggest to the user to restart it.
Capturing bad_alloc in the main loop can be useful if the allocation failure has been caused by another error, such as requiring 1 byte of memory, which when converted to unsigned gives a giant number. In this case, the allocation error does not indicate that the system is out of memory, but rather that it has failed to validate some parameter in its code, since the program should not request that colossal amount of memory.
If your program needs to run continuously, consider creating a supervisory process that restarts the program whenever it is detected that it terminated unexpectedly. The new process created will start over again in a much more predictable state than a program that attempted to handle a bad_alloc exception!
So that bad_alloc does not come as a surprise in the middle of an operation, you could pre-allocate enough memory and just work inside it. But be careful because the system allocator might have some write / read protections outside the allocated area that you will lose if you try to implement everything manually (cof, OpenSSL, cof, Heartbleed, cof).
To handle bad_alloc, you can pre-allocate a memory space and leave it unused, releasing only when there is an allocation error. I've heard of this parachute technique.
Note that all (except the first) options are labor-intensive and depend on how your program works (interactive "batch operations" can be restarted and continue where you left off). It will be necessary to simulate situations of lack of memory to ensure that the treatment works properly, and to take care of specific problems of certain operating systems, such as overcommiting.
If you are implementing a language, a database, or some server, these security measures are superimportant. If you're implementing a Flappy Bird clone, not so much ...