Удаление массива символов - PullRequest
23 голосов
/ 18 апреля 2009

Этот вопрос относится к этому . Учитывая этот код:

char *p = new char[200];
delete[] p;

что произойдет, если вы установите p[100] = '\0' перед удалением p?

У меня был какой-то код, в котором я получил ошибку отладки, когда пытался удалить не завершенный нулем массив символов, что-то об удалении памяти кучи, которая не назначена. Казалось, что он удаляет память за пределы массива.

Ответы [ 6 ]

40 голосов
/ 18 апреля 2009

код:

char *p = new char[200];
p[100] = '\0';
delete[] p;

отлично подходит для C ++. delete не знает или не заботится о строках с нулевым символом в конце, поэтому ваша ошибка должна быть вызвана другой причиной.

8 голосов
/ 18 апреля 2009

Ничего особенного не произойдет. Вы могли бы написать в каком-то месте в середине выделенной памяти (100 байт от начала, 99 байтов до конца выделенной памяти).

Тогда вы освободите эту выделенную память. Компилятор будет обрабатывать его именно так, как мы и ожидали. Память, выделенная этим, совершенно не связана с завершенными нулем строками. Вы можете вставить все, что вы хотите в эту память. Это какой-то «сырой» кусок памяти, вы даже можете создать какой-нибудь произвольный объект C ++ в эту память (размещение нового).

Ваша ошибка где-то еще. Например, здесь есть одна распространенная ошибка, когда конструктор вызывается один раз, а деструктор вызывается дважды, дважды удаляя что-то:

struct A { P *p; A() { p = new P; } ~A() { delete p; } };
A getA() { return A(); } int main() { A a = getA(); }

Теперь происходит то, что конструктор по умолчанию вызывается один раз, а созданный объект копируется ноль или более раз. Но деструктор запускается для каждой созданной копии. Таким образом, вы будете вызывать деструктор по указателю более одного раза, что приводит к таким странным ошибкам. Правильный способ исправить , что , - это использовать умный указатель, такой как shared_ptr. В качестве упражнения вы также можете обойтись без этого, написав соответствующие конструкторы копирования, которые копируют объект и выделяют память в конструкторе копирования, так что копия и соответствующий исходный объект сохраняют разные указатели.

6 голосов
/ 18 апреля 2009

Я думаю, что вы путаете простой старый массив char с массивом char, представляющим строку в стиле C. Оператор удаления C ++ не заботится о строковом массиве в стиле C. Все, что он когда-либо увидит, это набор символов. Это действительно ничем не отличается от, скажем, удаления массива int.

Наличие или отсутствие нулевого терминатора имеет значение только в функциях, которые обрабатывают char* как строку стиля C.

3 голосов
/ 18 апреля 2009

Это не должно иметь значения. delete [] должен использоваться для удаления динамически размещенного массива независимо от его содержимого.

1 голос
/ 18 апреля 2009

Насколько я могу судить, это должно работать просто отлично. Вы выделяете кусок памяти, и ОС должна следить за этим и иметь возможность освобождать его по запросу. Не должно иметь значения, какие значения вы помещаете в выделенный буфер.

Вставка NULL в середину символьного массива, безусловно, помешает строковым функциям C, таким как strcmp, strlen и т. Д., Но это совсем другое дело.

0 голосов
/ 18 апреля 2009

Как уже отмечали другие, код, который вы разместили, абсолютно действителен и не должен вызывать никаких проблем.

Ошибка могла быть вызвана изменением значения p где-то между.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...