lego69
lego69

Reputation: 1433

Unable to free const pointers in C

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

Answers (12)

free
free

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

rstalekar
rstalekar

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

uncleremus
uncleremus

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

user50049
user50049

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

MMasterSK
MMasterSK

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

nlstd
nlstd

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

Puppy
Puppy

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

Taoufik
Taoufik

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

Paul R
Paul R

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

Michael Mrozek
Michael Mrozek

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

Felix Kling
Felix Kling

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

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

Related Questions