tags:

views:

523

answers:

8

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
A: 

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);
el.pescado
In C++, you can `delete` a `const char*`. And why shouldn't you? The fact that the pointer prevents the characters from being modified shouldn't disallow to delete the string once it isn't needed anymore. I don't know C well enough, though. Anyone with a quote from the std here?
sbi
-1, the constness of a pointer doesn't affect your ability to `free` it in any way.
Hasturkun
`void free(void *ptr);` - you cannot pass const pointer to it. Unless, you cast it to non-const.
el.pescado
@el.pecado: `gcc -Wall` just gives a warning when you pass a pointer to const to `free()` - what compiler are you using that does not allow this ?
Paul R
@Paul "just gives a warning"? It's not like warnings don't matter or something. Personally I think it should be an error, passing a const to something that takes a non-const is not ok; in C++ they did upgrade it
Michael Mrozek
@Michael: I agree that, in general, warnings should always be fixed, but there is a big different between a warning and saying that you "cannot" do something.
Paul R
@Paul R: Warnings are usually signals that the compiler thinks it knows how to proceed, but thinks you might have made a mistake or are doing something nonstandard. In this case, it's nonstandard, which means that you cannot do something in a conforming way. At this point, you seem to be using a compiler extension.
David Thornley
@Paul True, I was looking at Hasturkun's "the constness of a pointer doesn't affect your ability to free it in any way" and wrongly assuming you were saying the same
Michael Mrozek
Hastturkun is wrong. `const char *` means that what the pointer is pointing to is constant, not that the pointer itself is constant. It is wrong to try to free a `const char *`. Consider `const char* foo = "bar"; free((void*) foo);` What is going to happen?
JeremyP
@JeremyP: The answer is Undefined Behavior (or possibly nasal demons), but that's not caused by the `const` so much as by trying to free a string constant.
Hasturkun
@JeremyP That example is specious; it's wrong, but not because the string is const, it's just a special case of string literals
Michael Mrozek
It's not *caused* by the `const` but the `const` ells the compiler something about what it is allowed to do to the string or not. If you see a function declaration `void foo(const char* bar)` that is a contract between the caller of foo and foo that says "foo will not change the char that bar points to. If foo passes bar to free, then foo is breaking the contract. You should never free a const char*.
JeremyP
In my example, at run time you are likely to get some sort of memory protection error that terminates your program. Had I left out the cast to void* I would have got a compile time warning to show that I have done something wrong. The example is trivial, but imagine a few thousand lines between the definition and the call to free or the pointeer being passed to another function that frees whatever is passed to it.
JeremyP
@JeremyP: "You should never free a `const char*`." I disagree. If that was true, you should never have `const` strings that are dynamically allocated, because you couldn't delete them. And that's just stupid. Whether something is allocated dynamically and whether it should not be altered are orthogonal questions. I can have dynamically allocated strings which I don't want to have altered, but which have to be freed at some point. I consider this a bug in the C std lib, probably stemming from the fact that C adopted `const` from C++ only later and it's now somewhat like a red-haired step child.
sbi
A: 

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.

Felix Kling
`free` doesn't change the pointer. It frees the memory block the pointer is pointing to. This is a mistake in the language specification. `free` should clearly take a const pointer.
Axel Gneiting
@Axel `const` means that you cannot change the contents of the storage object, not the actual value of the pointer... and freeing the pointed memory is a quite dramatic change I'd say! (BTW It seems a little bit pretentious to think that the specification is wrong [and has been wrong for more than 30 years] and suddenly you discover that you're right and all the review board members weren't, isn't it?)
fortran
@fortran: it's not at all pretentious, it's a common difference of opinion. `delete` in C++ can be used on a `const char*`, so if it's a big controversy then one or the other set of standard authors must be wrong. Actually I don't think it really matters - casting away const to free a pointer is hardly a crisis.
Steve Jessop
const char* says that what is being pointed to is a constant and cannot be changed. It is *not* saying that the pointer itself cannot be changed.
JeremyP
Free does not change pointer. It does not change value pointed to directly, *but* it may be returned by subsequent calls to malloc and used by other portions of code, so I think free changes what its argument points to, at least indirectly.
el.pescado
@Axel Gneiting: I never said that the pointer is changed. `const` indicates that the *data* at this location should not be changed. But if you free the memory, the data at this location can be overwritten and therefore changed.
Felix Kling
But free() actually changes the pointer. It becomes invalid, and using it in any way (even reading its value) is then undefined behaviour. Annex J.2: "The behavior is undefined in the following circumstances: [...] The value of a pointer to an object whose lifetime has ended is used (6.2.4)."
Secure
+2  A: 

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);
Michael Mrozek
It will work, but casting `const` to non-const is a symptom of code smell.
el.pescado
@el. `free()` is something of an exception, because you may not want the pointer to be modified during its lifetime, but you still want to free it at the end
Michael Mrozek
You can always store original pointer somewhere.
el.pescado
Why the cast to char * ? why not directly free((void *) str) ?
philippe
@philippe Either works, I just figured I'd illustrate that the problem isn't passing free a char* instead of a void* (which was one of the answers, although I think it's deleted now), it's passing a const char* instead of a non-const char*/void*
Michael Mrozek
@el. Sure, but that seems rather unnecessary. I'm not going to keep two pointers to the same place around, one const and one not, just so I can free the non-const one at the end without using an evil cast
Michael Mrozek
You should still get a warning for casting away const-ness, so I'm not sure that this is any better a solution than just passing the pointer to const as it is.
Paul R
I recall reading about a memory deallocation function in the linux kernel that took a const pointer, and someone asked Linus why, and he defended it as saying it doesn't actually modify the value pointed to, either conceptually or in practice, it merely looks up the memory block using the pointer and deallocates it. I concur with his assessment, and thus view the free() function's specification as incorrect. But alas, it is the standard.
rmeador
It's not the right answer. The whole point of const char* is that what is being pointed to cannot be changed. That includes freeing.
JeremyP
@Paul: Why should you? if this happens implicitly, sure, but the compiler shouldn't interfere with the programmer's (probably legitimate) explicit cast.
Hasturkun
I agree with @Hasturkun, you don't get warnings for casting; casting is specifically to say "trust me, I want the value as this type, and I don't want to argue about it"
Michael Mrozek
@JeremyP I don't think "freeing is a form of changing" is as uncontested as you think; see rmeador's comment, for example
Michael Mrozek
If "freeing" was conceptually changing, then is it OK to declare a `const int` and then leave the scope in which it was declared? That "frees" the automatic variable, in the sense of releasing the resource and making pointers to it no longer valid. It's just a quirk that `free` takes non-const, it's not a commandment from on high. In the rare case that there's only one thing you do with your pointer that's non-const, and that's free it, then pragmatically you probably get more benefit from a const pointer (which you cast to free) than a non-const pointer (which you might accidentally modify).
Steve Jessop
This does not fix the fact that the OP reversed their storage types.
Tim Post
+4  A: 

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 ?

Paul R
A: 

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 !!

Taoufik
A: 

If you are in C++, I know you put C, but I was wondering if you were in C++, you can use the following:

  free(const_cast<char*>(str));

This will change the const char* into a char * which can be used by free().

However, you should be wondering if what you are writing makes sense when you start using const_cast ...

BlueTrin
You should also be wondering if what you are writing makes sense when you use `free()` and C++ constructs.
David Thornley
+2  A: 

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.

DeadMG
+1  A: 

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).

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 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() behaves as expected and you can actually use the memory that you allocate.

Tim Post