Существует строка стиля C, и мне нужно освободить память. Я видел следующий пример кода, но смутился о том, почему (void*)
есть.
char *data = "abc";
free( (void*)data );
Всего два вопроса:
Почему бы не просто free(data)
?
Является ли (void*)
преобразование обязательным?
Большое спасибо.
Нет, это не обязательно; звонок free()
ошибочен, и вы не можете этого сделать.
Бросок - это огромный мигающий, подпрыгивающий и кричащий предупреждающий флаг, с которым запутался программист.
Это неопределенное поведение, чтобы передать указатель, не возвращенный предыдущим вызовом malloc()
или одному из его друзей, в free()
. Литье - это наименьшая проблема здесь.
Вы никогда не сможете "освободить" память, используемую строковым литералом, поскольку эта память никогда не выделяется каким-то образом, что программа контролирует. Это не в куче, а куча - это то, где обычно происходит распределение/освобождение динамической памяти. Ваше намерение неверно.
Все, что вы можете сделать, это установить указатель на NULL
:
data = NULL;
это никоим образом не "освободит" память, используемую за кулисами, для хранения символьных данных "abc"
хотя, но это прекрасно.
Является ошибкой для вызова free()
поскольку не выделяется с использованием (m/c/re)alloc
.
Как указал Йенс Густедт, приведение требуется только при передаче указателя const
потому что free()
принимает void *
, а не const void *
:
const int *x = malloc(sizeof(int));
free((void *)x);
Без броска вы получаете:
demo.c:8:5: warning: passing argument 1 of ‘free discards ‘const qualifier from pointer target type [enabled by default] In file included from demo.c:2:0: /usr/include/stdlib.h:488:13: note: expected ‘void * but argument is of type ‘const int *
const
, многие компиляторы жалуются.
Бросок не нужен. В C, void*
неявно конвертируется в и из других типов указателей. free
ожидает void*
, поэтому для другого типа указателя не требуется никакого перевода.
(Конечно, как уже указывалось, код явно проблематичен вообще, поэтому не читайте его слишком много.)
Итак, ваша предпосылка здесь неверна, вам не нужно вообще бесплатно "ваши данные", она, скорее всего, вызовет сбой, если вы это сделаете. Вы должны только звонить free
для данных, полученных из malloc
, и "abc"
не является одним из них.
Во-вторых, если вы используете C, вам следует:
char *data = malloc(4);
strcpy(data, "abc");
...
free(data);
В C++ мы также не можем преобразовать void *
[возвращаемое значение из malloc
] в char *
, поэтому вам понадобится char *data = (char *) malloc(4);
, но free(data)
должны по-прежнему работать. Некоторые компиляторы могут выдавать предупреждения для этого, а стандартная MISRA, например, не разрешает ЛЮБОЕ автоматическое преобразование типов C, поэтому явные приведения здесь НЕОБХОДИМО [не потому, что язык говорит так, а потому, что стандарт MISRA делает, и есть "проверка программного обеспечения", которое считывает исходный код для проверки такого рода критериев, выполняется].
Конечно, в "свежих" [1] C++ мы не должны использовать malloc
или free
, но new
и delete
:
char *data = new char[4];
strcpy(data, "abc");
....
delete [] data;
[1] Как в "коде, написанном как C++ с нуля".