Compartir a través de


_set_new_handler

Transfiere el control al mecanismo de control de errores si el operador new no puede asignar memoria. El compilador de Microsoft C++ usa esta función para implementarla std::set_new_handler en la biblioteca estándar.

Sintaxis

_PNH _set_new_handler( _PNH pNewHandler );

Parámetros

pNewHandler
Puntero a la función de control de memoria proporcionada por la aplicación. Un argumento de 0 o nullptr hace que se quite el nuevo controlador.

Valor devuelto

Devuelve un puntero a la función de control de excepciones anterior registrada por _set_new_handler para que después se pueda restaurar dicha función. Si no se ha establecido ninguna función anterior, el valor devuelto se puede usar para restaurar el comportamiento predeterminado. Este valor puede ser nullptr o 0.

Comentarios

La función _set_new_handler de C++ especifica una función de control de excepciones que obtiene el control si el operador new no puede asignar memoria. Si se produce un error en new, el sistema en tiempo de ejecución llama automáticamente a la función de control de excepciones que se pasó como argumento a _set_new_handler. _PNH, definido en <new.h>, es un puntero a una función que devuelve el tipo int y toma un argumento de tipo size_t. Use size_t para especificar la cantidad de espacio que se va a asignar.

No hay ningún controlador predeterminado.

_set_new_handler es básicamente un esquema de recopilación de elementos no utilizados. El sistema de tiempo de ejecución reintenta la asignación cada vez que la función devuelve un valor distinto de cero y se produce un error si la función devuelve 0.

Una repetición de la función _set_new_handler en un programa registra la función de control de excepciones especificada en la lista de argumentos con el sistema de tiempo de ejecución:

// _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];
}

De manera predeterminada, el _set_new_handler estado global de esta función está limitado a la aplicación. Para cambiarlo, consulte Estado global en CRT.

Puede guardar la dirección de la función que se pasó por última vez a la función _set_new_handler y restablecerla más adelante:

   _PNH old_handler = _set_new_handler( my_handler );
   // Code that requires my_handler
   // . . .
   _set_new_handler( old_handler )
   // Code that requires old_handler
   // . . .

La función _set_new_mode de C++ establece el nuevo modo de controlador para malloc. El nuevo modo de controlador indica si, en caso de error, malloc va a llamar a la rutina del nuevo controlador, según lo establecido por _set_new_handler. De forma predeterminada, malloc no llama a la rutina del nuevo controlador en caso de error al asignar memoria. Puede invalidar este comportamiento predeterminado para que, cuando malloc no pueda asignar memoria, malloc llame a la rutina del nuevo controlador de la misma forma que hace el operador new cuando se produce un error por la misma razón. Para invalidar el valor predeterminado, llame a _set_new_mode(1); al principio del programa o vincule con newmode.obj.

Si se proporciona un operator new definido por el usuario, las nuevas funciones de controlador no se llaman automáticamente en caso de error.

Para obtener más información, vea new y delete en el C++ Language Reference.

Hay un único _set_new_handler controlador para todos los archivos DLL o ejecutables vinculados dinámicamente en un único proceso. Incluso si llama a _set_new_handler, el controlador podría reemplazarse por otro. O bien, el nuevo controlador puede reemplazar un controlador establecido por otro archivo DLL o ejecutable en el proceso.

Requisitos

Función Encabezado necesario
_set_new_handler <new.h>

Para obtener más información sobre compatibilidad, consulte Compatibilidad.

Ejemplo

En este ejemplo, cuando se produce un error en la asignación, el control se transfiere a MyNewHandler. El argumento pasado a MyNewHandler es el número de bytes solicitados. El valor devuelto de MyNewHandler es una marca que indica si se debe reintentar la asignación: un valor distinto de cero indica que se debe reintentar la asignación, mientras que un valor de cero indica que se ha producido un error en la asignación.

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

Consulte también

Asignación de memoria
calloc
free
realloc