Ответ 1
Несколько человек опубликовали правильный ответ, но по какой-то причине они продолжают удалять его. Вам нужно направить его на указатель, отличный от константы; free
принимает значение void*
, а не const void*
:
free((char*)str);
Как я могу освободить const char*
? Я выделил новую память с помощью malloc
, и когда я пытаюсь ее освободить, я всегда получаю ошибку "несовместимый тип указателя"
Код, вызывающий это, выглядит примерно так:
char* name="Arnold";
const char* str=(const char*)malloc(strlen(name)+1);
free(str); // error here
Несколько человек опубликовали правильный ответ, но по какой-то причине они продолжают удалять его. Вам нужно направить его на указатель, отличный от константы; free
принимает значение void*
, а не const void*
:
free((char*)str);
Ваш код отменен.
Это:
char* name="Arnold";
const char* str=(const char*)malloc(strlen(name)+1);
Должно выглядеть так:
const char* name="Arnold";
char* str=(char*)malloc(strlen(name)+1);
Тип хранения const
сообщает компилятору, что вы не собираетесь изменять блок памяти после выделения (динамически или статически). Освобождение памяти изменяет его. Обратите внимание: вам не нужно вернуть возвращаемое значение malloc(), но это просто в стороне.
В динамическом распределении памяти (которое вы делаете, в зависимости от длины name
) мало используется, и сообщая компилятору, что вы не намерены его использовать. Обратите внимание, используя значение, пишущее что-то к нему, а затем (необязательно) освобождая его позже.
Приведение к другому типу хранения не устраняет тот факт, что вы сначала меняете типы хранения. Это просто заставляет предупреждение уходить, что пыталось вам что-то сказать.
Если код отменяется (как и должно быть), free()
будет работать так, как ожидалось, так как вы действительно можете изменить выделенную память.
Нет смысла переводить указатель на const, поскольку вы не сможете изменить его содержимое (без уродливых хаков).
FWIW, хотя gcc просто дает предупреждение для следующего:
//
// const.c
//
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
const char *p = malloc(100);
free(p);
return 0;
}
$ gcc -Wall const.c -o const
const.c: In function ‘main’:
const.c:8: warning: passing argument 1 of ‘free’ discards qualifiers from pointer target type
$
Какой компилятор вы используете?
Нет никакой цели в том, чтобы накладывать указатель malloc'd на const. Любая функция, которая принимает указатель const, не должна нести ответственность за освобождение памяти, которая была передана ему.
Есть случаи, когда вы хотите освободить const*
. Однако вы не хотите этого делать, если вы не назначили/не присвоили его в той же функции. Иначе вы, вероятно, сломаете вещи. См. Приведенный ниже код для примера в реальном мире. Я использую const
в объявлениях функций, чтобы показать, что я не изменяю содержимое аргументов. Однако он переназначен с двойным дублированием (strdup), который должен быть освобожден.
char* tolowerstring(const char *to_lower)
{
char* workstring = strdup(to_lower);
for(;workstring != '\0'; workstring++)
*workstring = tolower(workstring);
return workstring;
}
int extension_checker(const char* extension, const char* to_check)
{
char* tail = tolowerstring(to_check);
extension = tolowerstring(extension);
while ( (tail = strstr( tail+1, extension)) ) { /* The +1 prevents infinite loop on multiple matches */
if ( (*extension != '.' ) && ( tail[-1] != '.'))
continue;
if ( tail[strlen(extension)] == '\0') {
free(tail);
free( (char*) extension);
return 1;
}
}
free(tail);
free( (char *) extension);
return 0;
}
Я мог ошибаться, но я думаю, что проблема кроется в const
. Поместите указатель на не-const как:
free((char *) p);
Потому что с const
вы говорите: не меняйте данные, на которые указывает этот указатель.
Вы не можете освободить const char *
, потому что это const
. Указатели хранилища, полученные от malloc
в переменных, не являющихся константными, так что вы можете передать их в free
. Вы можете передать аргументы char *
для функций, принимающих аргументы const char *
, но противоположное не всегда верно.
void foo (const char *x);
char *ptr = malloc (...);
foo (ptr);
free (ptr);
Если вы говорите о чистом C, и вы полностью контролируете распределение памяти, вы можете использовать следующий трюк для приведения (const char *) в (char *), который не даст вам никаких предупреждений в компилятор:
const char *const_str = (const char *)malloc(...);
char *str = NULL;
union {
char *mutable_field_p;
const char *const_field_p;
} u;
u.const_field_p = const_str;
str = u.mutable_field_p;
Теперь вы можете использовать free (str); для освобождения памяти.
Но ОЗНАЧАЙТЕ, что это зло вне слов и должно использоваться только в строго контролируемой среде (например, библиотека, которая выделяет и освобождает строки, но не хочет позволять пользователю изменять их). В противном случае вы закончите сбой вашей программы когда кто-то предоставляет время компиляции "STRING" для вашей бесплатной функции.
Я думаю, что даже если вы укажете указатель на неконстантный, результат свободной воли будет зависеть от реализации. Обычно const был предназначен для переменной, которую вы не хотите изменять!