¿Puedo eliminar un puntero que apunta a una matriz asignada, pero no al inicio?

Me pregunto específicamente sobre la siguiente situación (que descubrí en algún código con el que tengo que trabajar):

SomeClass *ar = new SomeClass[2]; ar++; delete[] ar; 

Este código parece funcionar bien, es decir, no falla (win32, construido con VS2005).

¿Es esto “legal”? Ciertamente no se siente bien.

No, no está definido pasar ninguna dirección para delete que no haya sido devuelta por una new .
Aquí está la cita del Estándar.

§ 3.7.4.2-3

Si una función de desasignación finaliza arrojando una excepción, el comportamiento no está definido. El valor del primer argumento suministrado a una función de desasignación puede ser un valor de puntero nulo; si es así, y si la función de desasignación es una proporcionada en la biblioteca estándar, la llamada no tiene efecto. De lo contrario, el valor proporcionado al operador delete(void*) en la biblioteca estándar será uno de los valores devueltos por una invocación previa de cualquier operador new(std::size_t) u operator new(std::size_t, const std::nothrow_-t&) en la biblioteca estándar, y el valor proporcionado al operador delete[](void*) en la biblioteca estándar será uno de los valores devueltos por una invocación previa de cualquiera de los operator new[](std::size_t) o operator new[](std::size_t, const std::nothrow_t&) en la biblioteca estándar.

No, no es legal Solo puede delete lo que obtuvo de new , y lo mismo se aplica a new[] y delete[]

No, no es. Debe llamar a delete [] en la misma dirección (o puntero) que recibió de new []. Puede que tenga suerte de que no se cuelgue, pero definitivamente no borra la memoria de forma adecuada.

Referencias

De http://www.cplusplus.com/doc/tutorial/dynamic/

 The value passed as argument to delete must be either a pointer to a memory block previously allocated with new, or a null pointer (in the case of a null pointer, delete produces no effect). 

Desde http://msdn.microsoft.com/en-us/library/h6227113.aspx

 Using delete on a pointer to an object not allocated with new gives unpredictable results. You can, however, use delete on a pointer with the value 0. This provision means that, when new returns 0 on failure, deleting the result of a failed new operation is harmless. 

De documentos estándar ,. 5.3.5.2 Delete ,

… En la segunda alternativa (delete array), el valor del operando de delete será el valor del puntero que resultó de una matriz anterior new-expression.72) De lo contrario, el comportamiento no está definido. ….

También la nota secundaria 72) establece que,

72) Para matrices que no son de longitud cero, esto es lo mismo que un puntero al primer elemento de la matriz creada por esa nueva expresión. Las matrices de longitud cero no tienen un primer elemento.

Y así que sí, no está definido.

La norma establece que solo puede eliminar lo que asignó con nuevo, pero eso no explica por qué falla, o en este caso, no falla.

Cuando elimina un puntero, lo vuelve a colocar en el montón para usarlo nuevamente en futuras asignaciones. La implementación típica le da un puntero, con un int justo antes de que su puntero rastree la memoria en el bloque (esa es la implementación típica de malloc). Así, para un sistema típico de 32 bits.

  p-4 size here p--> +--------+ | your | | block | 

Por lo tanto, si señala en el medio del bloque, interpretará los bytes justo antes como un tamaño, con resultados potencialmente desastrosos. Fuiste salvado de ver el locking por tu pequeño ejemplo de código. Probablemente, nunca trataste de asignar después de ese punto. Si tratas de asignar algo después de eso, probablemente se bloqueará, porque tratará de reciclar parte de la memoria que acabas de devolver.

La razón exacta obviamente depende de la implementación. Esto es solo para explicar una forma común en que las eliminaciones incorrectas pueden fallar, no específicamente verificadas para Visual Studio 2005.

No es legal El hecho de que no se cuelgue no significa que no lo hará en otras circunstancias. Seguramente se bloqueará si activa el verificador. Y en cualquier caso, no liberará su matriz. Esto es solo el CRT / Windows que permite que su progtwig no se cuelgue cuando debería

enter image description here

Si no pasa el inicio, la delete no obtendrá la información adicional.