What can “new_handler” be used for in C++ besides

2019-02-10 02:34发布

问题:

C++ programs can define and set a new_handler() that should be called from memory allocation functions like operator new() if it's impossible to allocate memory requested.

One use of a custom new_handler() is dealing with C++ implementations that don't throw an exception on allocation failure. Another use is initiating garbage collection on systems that implement garbage collection.

What other uses of custom new_handler() are there?

回答1:

In a similar vein to the garbage collection application, you can use the new handler to free up any cached data you may be keeping.

Say that you're caching some resource data read from disk or the intermediate results of some calculation. This is data that you can recreate at any time, so when the new handler gets called (signifying that you've run out of heap), you can free the memory for the cached data, then return from the new handler. Hopefully, new will now be able to make the allocation.

In many cases, virtual memory can serve the same purpose: You can simply let your cached data get swapped out to disk -- if you've got enough virtual address space. On 32-bit systems, this isn't really the case any more, so the new handler is an interesting option. Many embedded systems will face similar constraints.



回答2:

On most of the servers I've worked on, the new_handler freed a pre-allocated block (so future new's wouldn't fail) before logging a message (the logger used dynamic memory) and aborting. This ensured that the out of memory error was correctly logged (instead of the process just "disappearing", with an error message to cerr, which was connected to /dev/null).

In applications such as editors, etc., it may be possible to spill parts of some buffers to disk, then continue; if the new_handler returns, operator new is supposed to retry the allocation, and if the new_handler has freed up enough memory, the allocation may succeed (and if it doesn't, the new_handler will be called again, to maybe free up even more).



回答3:

I've never used it for anything - too many OS will grant virtual memory and SIGSEGV or similar if they can't provide it later so it's not a good idea to make a system that relies on being memory-exhaustion tolerant: it's often outside C++'s hands. Still, if you developed for a system where it could/must be relied upon, I can easily imagine a situation where some real-time data was being streamed into a queue in your process, and you were processing it and writing/sending out results as fast as you could (e.g. video hardware streaming video for recompression to disk/network). If you got to the stage where you couldn't store any more, you'd simply have to drop some, but how would you know when it got that bad? Setting an arbitrary limit would be kind of silly, especially if your software was for an embedded environment / box that only existed to do this task. And, you probably shouldn't use a function like this casually on a system with any kind of hard-disk based swap memory, as if you're already into swap you're throughput rates would be miserable ever after. But - past the caveats - it might be useful to drop packets for a while until you catch up. Perhaps dropping every Nth frame through the queued buffer would be less visible than dropping a chunk at the back or front of the queue. Whatever, discarding data from the queue could be a sane application-level use (as distinct from intra-memory-subsystem) for something like this....