Подтвердить что ты не робот

Можно ли удалить [] указатель, который указывает на выделенный массив, но не на начало его?

Мне интересно узнать о следующей ситуации (которую я обнаружил в некотором коде, с которым мне нужно работать):

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

Этот код работает нормально, т.е. не сбой (win32, построенный на VS2005).

Является ли это "законным"? Конечно, это не так.

4b9b3361

Ответ 1

Нет, undefined передать любой адрес delete, который не был возвращен new.
Вот цитата из Стандарта.

§ 3.7.4.2-3

Если функция освобождения завершается путем исключения исключения, поведение undefined. Значение первого аргумента, переданного функции освобождения, может быть значением нулевого указателя; если это так, и если функция освобождения включена в стандартную библиотеку, вызов не действует. В противном случае заданное значение оператору delete(void*) в стандартной библиотеке должно быть одно из значений, возвращаемых предыдущим вызовом любого оператора new(std::size_t) или operator new(std::size_t, const std::nothrow_-t&) в стандартной библиотеке, а значение, предоставленное оператору delete[](void*) в стандартной библиотеке, должно быть одно из значений, возвращаемых предыдущим вызовом либо operator new[](std::size_t), либо operator new[](std::size_t, const std::nothrow_t&) в стандартной библиотеке.

Ответ 2

Нет, не законно. Вы можете только delete получить то, что вы получили от new, и то же самое относится к new[] и delete[]

Ответ 3

Нет, это не так. Вы должны вызвать delete [] по тому же адресу (или указателю), который вы получили от нового []. Возможно, вам повезет, что он не сбой, но он определенно не очищает память.

Ссылки:

Из 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).

От 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.

Ответ 4

Из стандартных документов. 5.3.5.2 Delete,

... Во втором альтернативный (удалить массив), значение операнда удаления должно быть значением указателя, которое было результатом предыдущего array new-expression.72) Если нет, поведение undefined.....

Также в примечании 72) указано, что

72) Для массивов без нулевой длины это то же самое, что и указатель на первый элемент массива, созданный этим новым выражением. Матрицы нулевой длины не имеют первый элемент.

И да, это undefined.

Ответ 5

В стандарте указано, что вы можете удалить только то, что вы назначили новым, но это не объясняет, почему он сбой или в этом случае не сбой.

Когда вы удаляете указатель, вы кладете его обратно в кучу, чтобы снова использоваться в будущих распределениях. Типичная реализация дает вам указатель с int непосредственно перед вашим указателем, отслеживающим память в блоке (что типичная реализация malloc). Как это, для типичной 32-разрядной системы.

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

Итак, если вы укажете на середину блока, он будет интерпретировать байты непосредственно перед ним как размер с потенциально катастрофическими результатами. Вы были спасены от просмотра аварии по вашему маленькому примеру кода. Наверное, вы никогда не пытались выделить после этого момента. Если вы попытаетесь выделить что-то после этого, это, вероятно, произойдет сбой, потому что он попытается переработать часть памяти, которую вы только что вернули.

Точная причина, очевидно, зависит от реализации. Это просто объяснение одного из распространенных способов неправильного удаления может привести к сбою, а не специально для Visual Studio 2005.

Ответ 6

Это не законно. Тот факт, что он не падает, не означает, что он не будет в других обстоятельствах. Это приведет к сбою, если вы включите верификатор. И в любом случае он не освободит ваш массив. Это всего лишь CRT/Windows, позволяющая вашей программе не вылетать, когда она должна

Ответ 7

введите описание изображения здесь

Если вы не пройдете его, delete не получит дополнительную информацию.