_set_new_handler
Transfère le contrôle à votre mécanisme de gestion des erreurs si l'opérateur new
ne peut pas allouer de mémoire. Le compilateur Microsoft C++ utilise cette fonction pour implémenter std::set_new_handler
dans la bibliothèque standard.
Syntaxe
_PNH _set_new_handler( _PNH pNewHandler );
Paramètres
pNewHandler
Pointeur vers la fonction de gestion de la mémoire fournie par l'application. Un argument de 0 ou nullptr
provoque la suppression du nouveau gestionnaire.
Valeur retournée
Retourne un pointeur vers la précédente fonction de gestion des exceptions enregistrée par _set_new_handler
, afin qu'elle puisse être restaurée plus tard. Si aucune fonction précédente n’a été définie, la valeur de retour peut être utilisée pour restaurer le comportement par défaut. Cette valeur peut être nullptr
ou 0.
Notes
La fonction C++ _set_new_handler
spécifie une fonction de gestion des exceptions qui prend le contrôle si l'opérateur new
ne peut pas allouer de mémoire. Si new
échoue, le système runtime appelle automatiquement la fonction de gestion des exceptions qui a été passée comme argument à _set_new_handler
. _PNH
, défini dans <new.h>
, est un pointeur vers une fonction qui retourne le type int
et prend un argument de type size_t
. Utilisez size_t
pour spécifier la quantité d'espace à allouer.
Il n’existe aucun gestionnaire par défaut.
_set_new_handler
est essentiellement un schéma du garbage collection. Le système runtime réexécute l'allocation chaque fois que la fonction retourne une valeur différente de zéro, et échoue si votre fonction retourne 0.
Une occurrence de la fonction _set_new_handler
dans un programme enregistre la fonction de gestion des exceptions spécifiée dans la liste d'arguments avec le système runtime :
// _set_new_handler1.cpp
#include <new.h>
int handle_program_memory_depletion( size_t )
{
// Your code
}
int main( void )
{
_set_new_handler( handle_program_memory_depletion );
int *pi = new int[BIG_NUMBER];
}
Par défaut, l’état global de la _set_new_handler
fonction est limité à l’application. Pour le modifier, consultez l’état global dans le CRT.
Vous pouvez enregistrer la dernière adresse de fonction passée à la fonction _set_new_handler
et la rétablir ultérieurement :
_PNH old_handler = _set_new_handler( my_handler );
// Code that requires my_handler
// . . .
_set_new_handler( old_handler )
// Code that requires old_handler
// . . .
La fonction C++ _set_new_mode
définit le nouveau mode de gestionnaire pour malloc
. Le nouveau mode de gestionnaire indique si, en cas d'échec, malloc
doit appeler la nouvelle routine de gestionnaire, telle qu'elle est définie par _set_new_handler
. Par défaut, malloc
n’appelle pas la nouvelle routine de gestionnaire en cas d’échec de l’allocation de mémoire. Vous pouvez remplacer ce comportement par défaut de sorte que, quand _malloc
ne parvient pas à allouer de la mémoire, malloc
appelle la routine de nouveau gestionnaire de la même façon que l’opérateur new
quand il échoue pour la même raison. Pour remplacer la valeur par défaut, appelez _set_new_mode(1);
tôt dans votre programme ou lien avec newmode.obj
.
Si un utilisateur défini operator new
est fourni, les nouvelles fonctions de gestionnaire ne sont pas automatiquement appelées en cas d’échec.
Pour plus d’informations, consultez new
et delete
dans la référence du langage C++.
Il existe un seul _set_new_handler
gestionnaire pour toutes les DLL ou exécutables liés dynamiquement dans un seul processus. Même si vous appelez _set_new_handler
, votre gestionnaire peut être remplacé par un autre. Ou bien, votre nouveau gestionnaire peut remplacer un gestionnaire défini par une autre DLL ou exécutable dans votre processus.
Spécifications
Fonction | En-tête requis |
---|---|
_set_new_handler |
<new.h> |
Pour plus d’informations sur la compatibilité, consultez Compatibility.
Exemple
Dans cet exemple, lorsque l’allocation échoue, le contrôle est transféré vers MyNewHandler
. L’argument passé est MyNewHandler
le nombre d’octets demandés. La valeur retournée est un indicateur indiquant si l’allocation doit être retentée : une valeur différente de MyNewHandler
zéro indique que l’allocation doit être retentée et qu’une valeur zéro indique que l’allocation a échoué.
// crt_set_new_handler.cpp
// Build for x86.
// WARNING: This code intentionally allocates memory until an allocation fails.
// Running this code can cause your system to become non-responsive.
#include <iostream>
#include <new>
#include <new.h>
static const int Big_number = 0x03FFFFFF;
struct MemoryHog {
int pork[Big_number];
};
class MemoryReserve {
MemoryHog* reserved = nullptr;
public:
MemoryReserve() {
reserved = new MemoryHog();
}
~MemoryReserve() noexcept {
if (reserved != nullptr)
delete reserved;
}
bool free_reserve() noexcept {
if (reserved != nullptr) {
delete reserved;
reserved = nullptr;
return true; // return true if memory freed
}
return false; // reserved memory exhausted.
}
};
// Global singleton for a MemoryReserve object
static MemoryReserve reserve{};
// Define a function to be called if new fails to allocate memory.
int MyNewHandler(size_t /* unused */)
{
// Call a function to recover some heap space. Return 1 on success.
if (reserve.free_reserve()) {
std::cerr << "MyNewHandler: Released reserved memory.\n";
return 1;
}
std::cerr << "MyNewHandler: Reserved memory exhausted.\n";
return 0;
}
static const int max_depth = 16; // recursion depth limiter
static int depth = 0;
void RecurseAlloc() {
MemoryHog* piggy = new MemoryHog{};
if (++depth < max_depth) // Recurse until memory exhausted or max_depth
RecurseAlloc();
depth--;
delete piggy;
return;
}
int main()
{
try {
_set_new_handler(MyNewHandler); // Set handler for new.
RecurseAlloc();
}
catch (std::bad_alloc& ex) {
std::cerr << "bad_alloc caught: " << ex.what() << '\n';
}
}
/* Output:
MyNewHandler: Released reserved memory.
MyNewHandler: Reserved memory exhausted.
bad_alloc caught: bad allocation
*/