Partager via


_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
*/

Voir aussi

Allocation de mémoire
calloc
free
realloc