Reputation: 1433
How can I free a const char*
? I allocated new memory using malloc
, and when I'm trying to free it I always receive the error "incompatible pointer type"
The code that causes this is something like:
char* name="Arnold";
const char* str=(const char*)malloc(strlen(name)+1);
free(str); // error here
Upvotes: 92
Views: 72386
Reputation: 11
I think the real answer is that free should take a const
pointer argument and NULL
should be defined as a const
pointer. This seems to be a bug in the standards. Freeing a const
pointer should be implemented as follows:
free(p);
p = NULL;
I don't see how a compiler could generate incorrect code in this case, the const
pointer p
is no longer accessible, so it doesn't matter if the object it pointed to is const
, valid, whatever else. Its const
so there can't be any dirty copies in registers or anywhere else. It is valid to set a const
pointer to another value, and the fact that that value is NULL
doesn't matter because the previous value is no longer accessible.
Upvotes: 1
Reputation: 359
If you take a look at the signature of free function , free always takes void* ptr as an argument therefore you need to cast it to the appropriate type i.e. free((void *)str); free does not allow const pointers to be deallocated directly therefore you need to cast it to non const type
Upvotes: -1
Reputation: 383
Several answers have suggested simply casting to char*
. But as el.pescado wrote above,
casting
const
to non-const
is a symptom of code smell.
There are compiler warnings that guard against this, such as -Wcast-qual
in gcc, which I find very useful. If you really have a valid case for freeing a const
pointer (contrary to what many have written here, there are valid cases, as pointed out by nlstd), you could define a macro for that purpose like this:
#define free_const(x) free((void*)(long)(x))
This works at least for gcc. The double cast makes the logic -Wcast-qual
not detect this as "casting const away". Needless to say, this macro should be used with care. Actually it should only be used for pointers allocated in the same function.
Upvotes: 2
Reputation:
Your code is reversed.
This:
char* name="Arnold";
const char* str=(const char*)malloc(strlen(name)+1);
Should look like this:
const char* name="Arnold";
char* str=(char*)malloc(strlen(name)+1);
The const
storage type tells the compiler that you do not intend to modify a block of memory once allocated (dynamically, or statically). Freeing memory is modifying it. Note, you don't need to cast the return value of malloc(), but that's just an aside.
There is little use in dynamically allocating memory (which you are doing, based on the length of name
) and telling the compiler you have no intention of using it. Note, using meaning writing something to it and then (optionally) freeing it later.
Casting to a different storage type does not fix the fact that you reversed the storage types to begin with :) It just makes a warning go away, which was trying to tell you something.
If the code is reversed (as it should be), free()
will work as expected since you can actually modify the memory that you allocated.
Upvotes: 30
Reputation: 17
If you are talking about pure C and you are in complete control of the memory allocation you can use the following trick to cast (const char *) to (char *) which will not give you any warning in compiler:
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;
Now you can use free(str); to free the memory.
But BEWARE that this is evil beyond words and should be only used in strictly controlled environment (e.g. library which allocates and frees strings, but doesn't want to allow user to modify them) Otherwise you will end up with your program crashing when someone provides compile time "STRING" to your free function.
Upvotes: 0
Reputation: 41
There are cases you want to free a const*
. However you don't want to do it unless you allocate/asign it in the same function. Else you are likely to break things. See the code below for a real world example. I use const
in the function declarations to show that I am not changing the content of the arguments. However it is reassigned with a lowercased duplicate (strdup) that needs to be freed.
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;
}
Upvotes: 4
Reputation: 147036
There's no purpose in casting a malloc'd pointer to const. Any function that takes a const pointer should not be responsible for freeing the memory that was passed to it.
Upvotes: 3
Reputation: 9
I think even if you cast the pointer to a non-const, the result of free will depends on the implementation. Normally const was designed for variable that you don't want to modify !!
Upvotes: -2
Reputation: 213190
It makes no sense to malloc a pointer to const, since you will not be able to modify its contents (without ugly hacks).
FWIW though, gcc just gives a warning for the following:
//
// 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
$
What compiler are you using ?
Upvotes: 6
Reputation: 175705
Several people have posted the right answer, but they keep deleting it for some reason. You need to cast it to a non-const pointer; free
takes a void*
, not a const void*
:
free((char*)str);
Upvotes: 118
Reputation: 817138
I could be wrong but I think the problem lies in const
. Cast the pointer to non-const like:
free((char *) p);
Because with const
you say: Don't change the data this pointer points to.
Upvotes: 1
Reputation: 19236
You cannot free const char *
because it is const
. Store pointers received from malloc
in non-const pointer variables, so that you can pass them to free
. You can pass char *
arguments to functions taking const char *
arguments but opposite is not always true.
void foo (const char *x);
char *ptr = malloc (...);
foo (ptr);
free (ptr);
Upvotes: -4