operador new c++ visual-c++ memory-management new-operator vc6

c++ - new - ¿Nueva devolución NULL en cualquier caso?



new int en c (3)

Sé que de acuerdo con el estándar C ++ en caso de que el nuevo no pueda asignar memoria, se supone que lanzará la excepción std :: bad_alloc. Pero he oído que algunos compiladores como VC6 (¿o la implementación de CRT?) No se adhieren a él. Es esto cierto ? Estoy preguntando esto porque al buscar NULL después de cada nueva declaración, el código se ve muy feo.


Me gustaría agregar la opinión (un tanto controvertida) de que buscar NULL después de un intento de asignación es prácticamente un ejercicio inútil. Si su programa alguna vez se encuentra con esa situación, lo más probable es que no pueda hacer mucho más que salir rápido. Es muy probable que cualquier intento de asignación posterior también fallará.

Sin buscar NULL, el código subsiguiente intentará desreferenciar un puntero NULL, que tiende a salir del programa rápidamente, con una condición de salida relativamente única (y fácilmente depurable).

No estoy intentando convencerte de que no busques NULL, sin duda es una programación concienzuda. Pero no obtiene mucho de ello, a menos que en casos muy específicos en los que pueda almacenar alguna información de recuperación (sin asignar más memoria), o memoria menos libre, etc. Pero esos casos serán relativamente raros para la mayoría de las personas.

Dado esto, solo confiaría en que el compilador lanzará bad_alloc, personalmente, al menos en la mayoría de los casos.


Según las especificaciones de C ++, siempre arrojará std :: bad_alloc cuando use simplemente nuevo sin params, pero por supuesto puede haber algunos compiladores no conformes.

Sin embargo, no codificaría para ser compatible con compiladores que no sean compatibles con C ++. VC6 es uno de ellos a este respecto.

Sin embargo, es una buena práctica configurar siempre el puntero a NULL después de eliminarlos. Por eso, todavía es necesario verificar NULL.

Dicho esto, aquí hay un par de opciones para limpiar su código:

Opción 1: configurar su propio controlador

Una forma segura de limpiar su código sería llamar primero a set_new_handler .

Luego puede verificar NULL en su controlador y lanzar std :: bad_alloc allí si se devuelve NULL.

Si te gustan las excepciones, esta es tu mejor apuesta. Si te gusta devolver NULL mejor, entonces también puedes hacerlo atrapando dentro de tu nuevo controlador.

Opción 2: Usar nuevo sobrecargado

El archivo de encabezado estándar de C ++ define un struct nohrow que está vacío. Puede usar un objeto de esta estructura dentro de new para obtener su versión sobrecargada que siempre devuelve NULL.

void* operator new (size_t size, const std::nothrow_t &); void* operator new[] (void *v, const std::nothrow_t &nt);

Entonces en tu código:

char *p = new(std::nothrow) char[1024];

Aquí hay una buena referencia para leer más


VC6 no cumplía por defecto a este respecto. El new VC6 devolvió 0 (o NULL ).

Aquí está el Artículo de KB de Microsoft sobre este tema junto con su solución alternativa sugerida utilizando un new controlador personalizado:

Si tiene un código anterior que se escribió para el comportamiento de VC6, puede obtener el mismo comportamiento con los compiladores de MSVC más nuevos (algo así como 7.0 y posteriores) vinculando en un archivo de objeto llamado nothrownew.obj . En realidad, existe un conjunto bastante complicado de reglas en los compiladores 7.0 y 7.1 (VS2002 y VS2003) para determinar si dejaron de lanzar o lanzar new .

Parece que MS limpió esto en 8.0 (VS2005), ahora siempre se convierte en un lanzamiento nuevo a menos que específicamente enlace a nothrownew.obj .

Tenga en cuenta que puede especificar que desea que new devuelva 0 lugar de arrojar std::bad_alloc utilizando el parámetro std::nothrow :

SomeType *p = new(std::nothrow) SomeType;

Esto parece funcionar en VC6, por lo que podría ser una forma de corregir más o menos mecánicamente el código para que funcione de la misma manera con todos los compiladores, para que no tenga que volver a procesar el manejo de errores existente.