There is a C-style string and I need to free the memory of it. I saw the following code sample but got confused about why (void*) is there.
char *data = "abc";
free( (void*)data );
Just two questions:
Why not simply free(data)?
Is (void*) conversion is a must?
Many thanks.
No, it's not necessary; the free() call is wrong and you cannot do this.
The cast is a huge blinking, bouncing, and screaming warning flag that the originating programmer was confused.
It's undefined behavior to pass a pointer not returned by a previous call to malloc() or one of its friends to free(). The cast is the least of the problems here.
You can never "free" the memory used by a string literal, since that memory is never allocated in some way that the program controls. It's not on the heap, and the heap is where dynamic memory allocation/deallocation typically happens. Your intention is wrong.
All you can do is set the pointer to NULL:
data = NULL;
that will not in any way "free" the memory used behind the scenes to hold the character data "abc" though, but that's fine.
Is an error to call free() since is not allocated using (m/c/re)alloc.
As pointed out by Jens Gustedt, a cast is only needed when you pass a const pointer because free() takes a void *, not a const void *:
const int *x = malloc(sizeof(int));
free((void *)x);
Without a cast you get:
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 *’
The cast is unnecessary. In C, a void* is implicitly convertible to and from other pointer types. free expects a void*, so no cast is required from another pointer type.
(Of course, as already pointed out, the code is obviously problematic altogether, so don't read into it too much.)
So, your premise here is incorrect, you do not need to free your "data" at all, it will most likely cause a crash if you do. You should only call free for data that has come from malloc, and "abc" is not one of those.
Second, if you are using C, then you should do:
char *data = malloc(4);
strcpy(data, "abc");
...
free(data);
In C++ we also can't convert a void * [the return value from malloc] to char *, so you would need char *data = (char *) malloc(4);, but free(data) should still work. Some compilers may issue warnings for this, and the standard MISRA, for example, does not allow ANY automatic conversions of C types, so explicit casts are REQUIRED here [not because the language says so, but because the MISRA standard does, and there are "checking software" that reads the source code to check these sort of criteria are met].
Of course, in "fresh"[1] C++, we should not use malloc or free, but new and delete:
char *data = new char[4];
strcpy(data, "abc");
....
delete [] data;
[1] As in "code written as C++ from scratch".
Related
I was trying strcpy like this:
int main()
{
char *c="hello";
const char *d="mello";
strcpy(c,d);
cout<<c<<endl;
return 0;
}
Compiling this gives a warning and running the code produces a Segmentation fault.
The warning is:
warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
char *c="hello";
The declaration of strcpy is: char * strcpy ( char * destination, const char * source );
So where am I wrong (regarding the warning)? IMO I have used a const char and a char, same as the function's declaration.
Does c* or d* not allocate memory to hold "hello" and "mello", due to
which it is throwing segmentation fault? How does the
initialization/definition of a variable like c* work?
Both variables are pointing to constant literal text.
Modifying constant literal text is undefined behavior.
Place the text into an array if you want to modify it:
char e[] = "fred";
e[0] = 'd';
Compiler warnings (and errors) always refer to a particular line of code (and a portion of that line as well). It's a good idea to pay close attention to where the problems are.
In your case, the warning is not about calling strcpy, but about initialising c. You're making a char *, a pointer to modifiable char, point to "hello", a read-only string literal. That's what the compiler is warning you about.
This used to be possible in C++, but with the caveat that you must never actually modify the memory pointed to (since string literals are immutable). Since C++11, converting a string literal to a char * is expicitly forbidden and will generate an error instead of a warning.
The reason for the segfault should be clear now: you're trying to overwrite a piece of read-only memory with the strcpy call.
The correct solution is to use writable memory for storing the destination string. You could do it like this:
char c[] = "hello";
This creates a new char array, which is writable normally (just like any other local variable), and initialises the array with the contents of the string literal (effectively a copy thereof).
Of course, since this is C++, you should be using std::string to store strings and not bother with char*, strcpy, and other C-isms at all.
The code you are trying is for TurboC++ it seems. As drescherjm pointed out in the comments, the char *c="hello"; is no longer legal in c++.
If you try out your code in Turbo C++, it'll work just as you expected, although this isn't the same case with the modern c++.
So where am I wrong (regarding the warning)? IMO I have used a const char and a char, same as the function's declaration.
The warning is due to the reason mentioned above, plus the warning isn't on the use of strcpy, it's on the declaration.
Does c* or d* not allocate memory to hold "hello" and "mello", due to which it is throwing segmentation fault? How does the initialization/definition of a variable like c* work?
Well, the compiler would just put the strings in to a random place in the memory and let the c/d pointer point to it. It's risky as you can lose the data if you make the pointer point to something else by accident.
void* buffer = (void*)malloc(100);
By prefixing the malloc() function with (void*), what is being achieved, are we overriding the return type?
Nothing is achieved since malloc already returns a void pointer. This is equivalent to:
void* buffer = malloc(100);
The return type of the call to malloc is being explicitly cast to a void pointer. This is sort of redundant, as it already returns a void*, but is probably possibly present to clarify the developer's intention (or he just screwed up).
In this particular case, it does nothing. However, since C++ is much more strict than C regarding type safety, you generally need to cast the return of malloc:
void* x = malloc(100); //OK in C/C++
int* y = malloc(100); //OK in C, error in C++
int* z = (int*)malloc(100); //OK in C/C++, not recommended for C
However, since you use C++, I can't not tell you that you should use new instead.
Code:
void *buff;
char *r_buff = (char *)buff;
I can't understand the type casting of buff. Please help.
Thank you.
buff is a pointer to some memory, where the type of its content is unspecified (hence the void).
The second line tells that r_buff shall point to the same memory location, and the contents shall be interpreted as char(s).
buff is typed as a void pointer, which means it points to memory without declaring anything about the contents.
When you cast to char *, you declare that you're interpreting the pointer as being a char pointer.
In well written C++, you should not use C-style casts. So your cast should look like this:
void *buff;
char *r_buff = static_cast<char *>(buff);
See here for an explanation of what the C++ casting operators do.
By its name, buff is likely to be a memory buffer in which to write data, possibly binary data.
There are reasons why one might want to cast it to char *, potentially to use pointer arithmetic on it as one is writing because you cannot do that with a void*.
For example if you are supplied also a size (likely) and your API requires not pointer and size but 2 pointers (begin and end) you will need pointer arithmetic to determine where the end is.
The code could well be C in which case the cast is correct. If the code is C++ though a static_cast is preferable although the C cast is not incorrect in this instance. The reason a static_cast is generally preferred is that the compiler will catch more occasions when you cast incorrectly that way, and it is also more easily greppable. However casting in general breaks type-safety rules and therefore is preferably avoided much of the time. (Not that it is never correct, as it may be here).
I got this problem:
invalid conversion from ‘void*’ to ‘uint8_t*’
When doing this:
int numBytes;
uint8_t *buffer;
buffer=malloc(numBytes); //error here, why?
or must I have to put it like this?
buffer=malloc(numBytes);
Please explain this.
You cannot implicitly cast from void * in C++ (unlike C in this respect). You could do:
buffer = static_cast<uint8_t *>(malloc(numBytes));
but really, you should just be using new/delete instead of malloc/free!
In C++ it is not allowed to simply assign a pointer of one type to a pointer of another type (as always there are exception to the rule. It is for example valid to assign a any pointer to a void pointer.)
What you should do is to cast your void pointer to a uint8_t pointer:
buffer = (uint8_t *) malloc (numBytes);
Note: This is only necessary in C++, in C it was allowed to mix and match pointers. Most C compilers give a warning, but it is valid code.
Since you're using C++ you could also use new and delete like this:
buffer = new uint8_t[numBytes];
and get rid of your buffer using:
delete[] buffer;
In general you shouldn't use malloc and free unless you have to interface with c libraries.
Malloc returns a void pointer; when you use it, you have to cast the return value to a pointer to whatever datatype you're storing in it.
buffer = (uint8_t *) malloc(numBytes);
Can someone explain this to me:
char* a;
unsigned char* b;
b = a;
// error: invalid conversion from ‘char*’ to ‘unsigned char*’
b = static_cast<unsigned char*>(a);
// error: invalid static_cast from type ‘char*’ to type ‘unsigned char*’
b = static_cast<unsigned char*>(static_cast<void*>(a));
// everything is fine
What makes the difference between cast 2 and 3? And are there any pitfalls if the approach from 3 is used for other (more complex) types?
[edit]
As some mentioned bad design, etc...
This simple example comes from an image library which gives me the pointer to the image data as char*. Clearly image intensities are always positive so I need to interpret it as unsigned char data.
static_cast<void*> annihilate the purpose of type checking as you say that now it points on "something you don't know the type of". Then the compiler have to trust you and when you say static_cast<unsigned char*> on your new void* then he'll just try to do his job as you ask explicitely.
You'd better use reinterpret_cast<> if you really must use a cast here (as it's obvioulsy showing a design problem here).
Your third approach works because C++ allows a void pointer to be casted to T* via static_cast (and back again) but is more restrictive with other pointer types for safety reasons. char and unsigned char are two distinct types. This calls for a reinterpret_cast.
C++ tries to be a little bit more restrictive to type casting than C, so it doesn't let you convert chars to unsigned chars using static_cast (note that you will lose sign information). However, the type void* is special, as C++ cannot make any assumption for it, and has to rely on the compiler telling it the exact type (hence the third cast works).
As for your second question, of course there are a lot of pitfals on using void*. Usually, you don't have to use it, as the C++ type system, templates, etc. is rich enough to not to have to rely in that "unknown type". Also, if you really need to use it, you have to be very careful with casts to and from void* controlling that types inserted and obtained are really the same (for example, not pointer to subclasses, etc.)
static_cast between pointers works correct only if one of pointers is void or that's casting between objects of classes, where one class is inherited by another.
The difference between 2 and 3 is that in 3, you're explicitly telling the compiler to stop checking you by casting to void*. If the approach from 3 is used for, pretty much anything that isn't a direct primitive integral type, you will invoke undefined behaviour. You may well invoke undefined behaviour in #3 anyway. If it doesn't cast implicitly, it's almost certainly a bad idea unless you really know what's going on, and if you cast a void* back to something that wasn't it's original type, you will get undefined behaviour.
Casts between pointers require reinterpret_cast, with the exception of void*:
Casts from any pointer to to void* are implicit, so you don't need to explicitly cast:
char* pch;
void* p = pch;
Casts from void* to any other pointer only require a static_cast:
unsigned char* pi = static_cast<unsigned char*>(p);
beware, when you cast to void* you lose any type information.
what you are trying to do is incorrect, and false, and error prone and misleading. that's why the compilator returned a compilation error :-)
a simple example
char* pChar = NULL; // you should always initalize your variable when you declare them
unsigned char* pUnsignedChar = NULL; // you should always initalize your variable when you declare them
char aChar = -128;
pChar = &aChar;
pUnsignedChar = static_cast<unsigned char*>(static_cast<void*>(pChar));
then, though pUnsignedChar == pChar nonethless we have *pUnsignedChar == 255 and *pChar == -128.
i do believe this is bad joke, thus bad code.