Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 90 additions & 62 deletions docs/c-runtime-library/reference/set-new-handler.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
description: "Learn more about: _set_new_handler"
title: "_set_new_handler"
ms.date: "4/2/2020"
ms.date: 05/21/2022
api_name: ["_set_new_handler", "_o__set_new_handler"]
api_location: ["msvcrt.dll", "msvcr80.dll", "msvcr90.dll", "msvcr100.dll", "msvcr100_clr0400.dll", "msvcr110.dll", "msvcr110_clr0400.dll", "msvcr120.dll", "msvcr120_clr0400.dll", "ucrtbase.dll", "api-ms-win-crt-runtime-l1-1-0.dll", "api-ms-win-crt-private-l1-1-0.dll"]
api_type: ["DLLExport"]
Expand All @@ -10,9 +10,9 @@ f1_keywords: ["_set_new_handler", "set_new_handler"]
helpviewer_keywords: ["_set_new_handler function", "set_new_handler function", "error handling", "transferring control to error handler"]
ms.assetid: 1d1781b6-5cf8-486a-b430-f365e0bb023f
---
# _set_new_handler
# `_set_new_handler`

Transfers control to your error-handling mechanism if the **`new`** operator fails to allocate memory.
Transfers control to your error-handling mechanism if the **`new`** operator fails to allocate memory. The Microsoft C++ compiler uses this function to implement [`std::set_new_handler`](../../standard-library/new-functions.md#set_new_handler) in the standard library.

## Syntax

Expand All @@ -22,27 +22,25 @@ _PNH _set_new_handler( _PNH pNewHandler );

### Parameters

*pNewHandler*<br/>
Pointer to the application-supplied memory handling function. An argument of 0 causes the new handler to be removed.
*`pNewHandler`*\
Pointer to the application-supplied memory handling function. An argument of 0 or `nullptr` causes the new handler to be removed.

## Return Value
## Return value

Returns a pointer to the previous exception handling function registered by **_set_new_handler**, so that the previous function can be restored later. If no previous function has been set, the return value can be used to restore the default behavior; this value can be **NULL**.
Returns a pointer to the previous exception handling function registered by **`_set_new_handler`**, so that the previous function can be restored later. If no previous function has been set, the return value can be used to restore the default behavior. This value can be `nullptr` or 0.

## Remarks

The C++ **_set_new_handler** function specifies an exception-handling function that gains control if the **`new`** operator fails to allocate memory. If **`new`** fails, the run-time system automatically calls the exception-handling function that was passed as an argument to **_set_new_handler**. **_PNH**, defined in New.h, is a pointer to a function that returns type **`int`** and takes an argument of type **size_t**. Use **size_t** to specify the amount of space to be allocated.
The C++ **`_set_new_handler`** function specifies an exception-handling function that gains control if the **`new`** operator fails to allocate memory. If **`new`** fails, the run-time system automatically calls the exception-handling function that was passed as an argument to **`_set_new_handler`**. **`_PNH`**, defined in `<new.h>`, is a pointer to a function that returns type **`int`** and takes an argument of type **`size_t`**. Use **`size_t`** to specify the amount of space to be allocated.

There is no default handler.
There's no default handler.

**_set_new_handler** is essentially a garbage-collection scheme. The run-time system retries allocation each time your function returns a nonzero value and fails if your function returns 0.
**`_set_new_handler`** is essentially a garbage-collection scheme. The run-time system retries allocation each time your function returns a nonzero value and fails if your function returns 0.

An occurrence of the **_set_new_handler** function in a program registers the exception-handling function specified in the argument list with the run-time system:
An occurrence of the **`_set_new_handler`** function in a program registers the exception-handling function specified in the argument list with the run-time system:

```cpp
// set_new_handler1.cpp
By default, this function's global state is scoped to the application. To change this, see [Global state in the CRT](../global-state.md).

// _set_new_handler1.cpp
#include <new.h>

int handle_program_memory_depletion( size_t )
Expand All @@ -57,7 +55,9 @@ int main( void )
}
```

You can save the function address that was last passed to the **_set_new_handler** function and reinstate it later:
By default, the **`_set_new_handler`** function's global state is scoped to the application. To change it, see [Global state in the CRT](../global-state.md).

You can save the function address that was last passed to the **`_set_new_handler`** function and reinstate it later:

```cpp
_PNH old_handler = _set_new_handler( my_handler );
Expand All @@ -68,81 +68,109 @@ You can save the function address that was last passed to the **_set_new_handler
// . . .
```

The C++ [_set_new_mode](set-new-mode.md) function sets the new handler mode for [malloc](malloc.md). The new handler mode indicates whether, on failure, **malloc** is to call the new handler routine as set by **_set_new_handler**. By default, **malloc** does not call the new handler routine on failure to allocate memory. You can override this default behavior so that, when **malloc** fails to allocate memory, **malloc** calls the new handler routine in the same way that the **`new`** operator does when it fails for the same reason. To override the default, call:
The C++ [`_set_new_mode`](set-new-mode.md) function sets the new handler mode for [`malloc`](malloc.md). The new handler mode indicates whether, on failure, **`malloc`** is to call the new handler routine as set by **`_set_new_handler`**. By default, **`malloc`** doesn't call the new handler routine on failure to allocate memory. You can override this default behavior so that, when **`malloc`** fails to allocate memory, **`malloc`** calls the new handler routine in the same way that the **`new`** operator does when it fails for the same reason. To override the default, call `_set_new_mode(1);` early in your program or link with *`newmode.obj`*.

```cpp
_set_new_mode(1);
```
If a user-defined `operator new` is provided, the new handler functions aren't automatically called on failure.

early in your program or link with Newmode.obj.
For more information, see [`new`](../../cpp/new-operator-cpp.md) and [`delete`](../../cpp/delete-operator-cpp.md) in the *C++ Language Reference*.

If a user-defined `operator new` is provided, the new handler functions are not automatically called on failure.

For more information, see [new](../../cpp/new-operator-cpp.md) and [delete](../../cpp/delete-operator-cpp.md) in the *C++ Language Reference*.

There is a single **_set_new_handler** handler for all dynamically linked DLLs or executables; even if you call **_set_new_handler** your handler might be replaced by another or that you are replacing a handler set by another DLL or executable.
There's a single **`_set_new_handler`** handler for all dynamically linked DLLs or executables in a single process. Even if you call **`_set_new_handler`**, your handler might be replaced by another. Or, your new handler may replace a handler set by another DLL or executable in your process.

## Requirements

|Routine|Required header|
|-------------|---------------------|
|**_set_new_handler**|\<new.h>|
| Function | Required header |
|--|--|
| **`_set_new_handler`** | `<new.h>` |

For more compatibility information, see [Compatibility](../../c-runtime-library/compatibility.md).

## Example

In this example, when the allocation fails, control is transferred to MyNewHandler. The argument passed to MyNewHandler is the number of bytes requested. The value returned from MyNewHandler is a flag indicating whether allocation should be retried: a nonzero value indicates that allocation should be retried, and a zero value indicates that allocation has failed.
In this example, when the allocation fails, control is transferred to `MyNewHandler`. The argument passed to `MyNewHandler` is the number of bytes requested. The value returned from `MyNewHandler` is a flag indicating whether allocation should be retried: a nonzero value indicates that allocation should be retried, and a zero value indicates that allocation has failed.

```cpp
// crt_set_new_handler.cpp
// compile with: /c
#include <stdio.h>
// 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>
#define BIG_NUMBER 0x1fffffff

int coalesced = 0;
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{};

int CoalesceHeap()
{
coalesced = 1; // Flag RecurseAlloc to stop
// do some work to free memory
return 0;
}
// Define a function to be called if new fails to allocate memory.
int MyNewHandler( size_t size )
int MyNewHandler(size_t /* unused */)
{
printf("Allocation failed. Coalescing heap.\n");

// Call a function to recover some heap space.
return CoalesceHeap();
// 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;
}

int RecurseAlloc() {
int *pi = new int[BIG_NUMBER];
if (!coalesced)
RecurseAlloc();
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()
{
// Set the failure handler for new to be MyNewHandler.
_set_new_handler( MyNewHandler );
RecurseAlloc();
try {
_set_new_handler(MyNewHandler); // Set handler for new.
RecurseAlloc();
}
catch (std::bad_alloc& ex) {
std::cerr << "bad_alloc caught: " << ex.what() << '\n';
}
}
```

```Output
Allocation failed. Coalescing heap.

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
/* Output:
MyNewHandler: Released reserved memory.
MyNewHandler: Reserved memory exhausted.
bad_alloc caught: bad allocation
*/
```

## See also

[Memory Allocation](../../c-runtime-library/memory-allocation.md)<br/>
[calloc](calloc.md)<br/>
[free](free.md)<br/>
[realloc](realloc.md)<br/>
[Memory allocation](../../c-runtime-library/memory-allocation.md)\
[`calloc`](calloc.md)\
[`free`](free.md)\
[`realloc`](realloc.md)
63 changes: 52 additions & 11 deletions docs/cpp/new-and-delete-operators.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
---
title: "new and delete operators"
description: "The C++ language new and delete operators allow control over allocation."
ms.date: 07/07/2020
ms.date: 05/21/2022
helpviewer_keywords: ["new keyword [C++]", "delete keyword [C++]"]
---
# `new` and `delete` operators

C++ supports dynamic allocation and deallocation of objects using the [`new`](new-operator-cpp.md) and [`delete`](delete-operator-cpp.md) operators. These operators allocate memory for objects from a pool called the free store. The **`new`** operator calls the special function [`operator new`](new-operator-cpp.md), and the **`delete`** operator calls the special function [`operator delete`](delete-operator-cpp.md).

The **`new`** function in the C++ Standard Library supports the behavior specified in the C++ standard, which is to throw a `std::bad_alloc` exception if the memory allocation fails. If you still want the non-throwing version of **`new`**, link your program with *`nothrownew.obj`*. However, when you link with *`nothrownew.obj`*, the default **`operator new`** in the C++ Standard Library no longer functions.
C++ supports dynamic allocation and deallocation of objects using the [`new`](new-operator-cpp.md) and [`delete`](delete-operator-cpp.md) operators. These operators allocate memory for objects from a pool called the *free store* (also known as the *heap*). The **`new`** operator calls the special function [`operator new`](new-operator-cpp.md), and the **`delete`** operator calls the special function [`operator delete`](delete-operator-cpp.md).

For a list of the library files in the C Runtime Library and the C++ Standard Library, see [CRT Library Features](../c-runtime-library/crt-library-features.md).

Expand All @@ -20,9 +18,9 @@ The compiler translates a statement such as this one into a call to the function
char *pch = new char[BUFFER_SIZE];
```

If the request is for zero bytes of storage, **`operator new`** returns a pointer to a distinct object. That is, repeated calls to **`operator new`** return different pointers. If there's insufficient memory for the allocation request, **`operator new`** throws a `std::bad_alloc` exception. Or, it returns **`nullptr`** if you've linked in non-throwing **`operator new`** support.
If the request is for zero bytes of storage, **`operator new`** returns a pointer to a distinct object. That is, repeated calls to **`operator new`** return different pointers.

You can write a routine that attempts to free memory and retry the allocation. For more information, see [`_set_new_handler`](../c-runtime-library/reference/set-new-handler.md). For details on the recovery scheme, see the [Handling insufficient memory](#handling-insufficient-memory) section.
If there's insufficient memory for the allocation request, **`operator new`** throws a `std::bad_alloc` exception. Or, it returns **`nullptr`** if you've used the *placement* form `new(std::nothrow)`, or if you've linked in non-throwing **`operator new`** support. For more information, see [Allocation failure behavior](#allocation-failure-behavior).

The two scopes for **`operator new`** functions are described in the following table.

Expand All @@ -33,7 +31,7 @@ The two scopes for **`operator new`** functions are described in the following t
| **`::operator new`** | Global |
| *class-name* **`::operator new`** | Class |

The first argument to **`operator new`** must be of type `size_t`, defined in \<stddef.h>, and the return type is always **`void*`**.
The first argument of **`operator new`** must be of type `size_t`, and the return type is always **`void*`**.

The global **`operator new`** function is called when the **`new`** operator is used to allocate objects of built-in types, objects of class type that don't contain user-defined **`operator new`** functions, and arrays of any type. When the **`new`** operator is used to allocate objects of a class type where an **`operator new`** is defined, that class's **`operator new`** is called.

Expand Down Expand Up @@ -94,24 +92,67 @@ int main()
}
```

### Allocation failure behavior

The **`new`** function in the C++ Standard Library supports the behavior specified in the C++ standard since C++98. When there's insufficient memory for an allocation request, **`operator new`** throws a [`std::bad_alloc`](../standard-library/bad-alloc-class.md) exception.

Older C++ code returned a null pointer for a failed allocation. If you have code that expects the non-throwing version of **`new`**, link your program with *`nothrownew.obj`*. The *`nothrownew.obj`* file replaces global **`operator new`** with a version that returns **`nullptr`** if an allocation fails. **`operator new`** no longer throws `std::bad_alloc`. For more information about *`nothrownew.obj`* and other linker option files, see [Link options](../c-runtime-library/link-options.md).

You can't mix code that checks for exceptions from global **`operator new`** with code that checks for null pointers in the same application. However, you can still create class-local **`operator new`** that behaves differently. This possibility means the compiler must act defensively by default and include checks for null pointer returns in **`new`** calls. For more information on a way to optimize these compiler checks, see [`/Zc:throwingnew`](../build/reference/zc-throwingnew-assume-operator-new-throws.md).

### Handling insufficient memory

Testing for failed memory allocation can be done as shown here:
The way you test for a failed allocation from a **`new`** expression depends on whether you use the standard exception mechanism, or you use a **`nullptr`** return. Standard C++ expects an allocator to throw either `std::bad_alloc` or a class derived from `std::bad_alloc`. You can handle such an exception as shown in this sample:

```cpp
#include <iostream>
#include <new>
using namespace std;
#define BIG_NUMBER 10000000000LL
int main() {
try {
int *pI = new int[BIG_NUMBER];
}
catch (bad_alloc& ex) {
cout << "Caught bad_alloc: " << ex.what() << endl;
return -1;
}
}
```

When you use the `nothrow` form of **`new`**, you can test for an allocation failure as shown in this sample:

```cpp
#include <iostream>
#include <new>
using namespace std;
#define BIG_NUMBER 10000000000LL
int main() {
int *pI = new(nothrow) int[BIG_NUMBER];
if ( pI == nullptr ) {
cout << "Insufficient memory" << endl;
return -1;
}
}
```

You can test for a failed memory allocation when you've used *`nothrownew.obj`* file to replace global **`operator new`** as shown here:

```cpp
#include <iostream>
#include <new>
using namespace std;
#define BIG_NUMBER 100000000
#define BIG_NUMBER 10000000000LL
int main() {
int *pI = new int[BIG_NUMBER];
if( pI == 0x0 ) {
if ( !pI ) {
cout << "Insufficient memory" << endl;
return -1;
}
}
```

There's another way to handle failed memory allocation requests. Write a custom recovery routine to handle such a failure, then register your function by calling the [`_set_new_handler`](../c-runtime-library/reference/set-new-handler.md) run-time function.
You can provide a handler for failed memory allocation requests. It's possible to write a custom recovery routine to handle such a failure. It could, for example, release some reserved memory, then allow the allocation to run again. For more information, see [`_set_new_handler`](../c-runtime-library/reference/set-new-handler.md).

## <a id="delete_operator"> </a> The `delete` operator

Expand Down
Loading