Okay, so I have a method which I call. The called method returns a char*, which is allocated inside the called method. After having assigned the returned char* to a new char*, I want to free this, after using it. But Xcode complains and throws an error. It says that the object I try to free is not allocated, which I do not get, since I am sure I allocate it.
Here is my code:
void print_r()
{
char *stateA = isActive(ruter_array[id]->flagg);
//print out the results etc
free(stateA); <-----The program crashes here.
}
char * isActive(unsigned char a_flag)
{
char *ret = malloc(5);
if((a_flag & 1) == 1)
{
//is active
ret = "yes";
return ret;
}
ret = "no";
return ret;
}
Its not important to understand what this does, but why is this freeing crashing?
ret = "no";
That overwrites the pointer. Change to:
strcpy(ret, "no");
Same applies for the "yes" case.
Also, as pointed out by #DavidSchwartz, for your purposes it is probably not necessary to use dynamically allocated memory. Could just return the string literals directly:
char * isActive(unsigned char a_flag)
{
if((a_flag & 1) == 1)
{
//is active
return "yes";
}
return "no";
}
And of course in that case the caller should not free the returned value.
You allocate some memory and assign the first address of that memory to the pointer ret, but "no" and "yes" are string literals that are stored statically in memory at compile-time. When you do ret = "no", you change the pointer so that it now points to the first character of the string literal "no". So, now you have lost access to the memory that you allocated, and you have a memory leak. But the crash is because you are trying to free memory that was not allocated by malloc() or one of its friends.
You can even use strdup:
char * isActive(unsigned char a_flag)
{
return strdup((a_flag & 1) == 1 ? "yes" : "no");
}
As written here the pointer is still allocated through malloc so it can also be freed.
Related
I'm a newbie to C. I had extended the question from the previous question: Strange behavior when returning "string" with C (Thanks for all who answered or commented that question, by the way.)
Pretty straight forward:
Why can this work:
#include <stdio.h>
int func() {
int i = 5;
return i;
}
int main() {
printf("%d",func());
}
But not this:
#include <stdio.h>
char * func() {
char c[] = "Hey there!";
return c;
}
int main() {
printf("%s",func());
}
From the previous question, logically the int i should not exist too because the function has returned, but why can it still be returned while char c[] cannot?
(It seems to be duplicated from "Pointers and memory scope" but I would like to know more about what is the difference between returning an int and a char *.)
Problem is not returning char *, it is returning something that is allocated on stack.
If you allocate memory for your string rather than pointing to function stack, there will be no problem. Something like this:
char * func() {
char c[] = "Hey there!";
return strdup(c);
}
int main() {
char* str = func();
printf("%s", str);
free(str);
}
It is important to mention that in both cases, you are copying a value and in both cases copied value is correct, but the meaning of copied value differs.
In first case, your are copying an int value and after your return from function, you are using that int value which will be valid. But in 2nd case, even though you have a valid pointer value, it refers to an invalid address of memory which is stack of called function.
Based on suggestions in comment, I decided to add another better practice in memory allocating for this code:
#define NULL (void*)0
int func(char *buf, int len) {
char c[] = "Hey there!";
int size = strlen(c) + 1;
if (len >= size) {
strcpy(buf, c);
}
return size;
}
int main() {
int size = func(NULL, 0);
char *buf = calloc(size, sizeof(*buf));
func(buf, size);
printf("%s", buf);
free(buf);
return 0;
}
Similar approach is used in a lot of windows API functions. This approach is better, because owner of pointer is more obvious (main in here).
In the first example the return value is copied. In your second example you're returning a pointer, which will point to a memory location which no longer exists.
In the first case, you return the int value 5 from the function. You can then print that value.
In the second case however, you return a value of type char *. That value points to an array that is local to the function func. After that function returns the array goes out of scope, so the pointer points to invalid memory.
The difference between these two cases is a value that you use directly, versus a pointer value that no longer points to valid memory. Had you returned a pointer to memory allocated by malloc, then the pointer would point to valid memory.
You are trying to return pointer to local array, which is very bad. If you want to return a pointer to array, allocate it dynamically using malloc inside your func();
Then you must call free() on caller side to free up memory you allocated when you no longer need it
In the first example, you return an int, and the second you return a pointer to a char. They both return in exactly the same manner, it is just a matter of understanding the stack and how values are returned.
Even though i was declared in the function and is allocated on the stack, when the function returns it returns the value of i (which is basically copied, so when i falls off the stack the value of i is still returned.)
This is the exact same thing that happens to the char * in the second example. It will still be a pointer to a char, and it returns the 'copied' value of c. However, since it was allocated on the stack, the address it points to is effectively invalid. The pointer value itself has not changed, but what it points to has.
You would have to dynamically allocate this to avoid this situation.
The return value of function is returned by copy. In the first example, you get a copy of the integer variable from the function. In the second you get a copy of the char pointer, not a copy of the string.
The pointer references the string data that has automatic storage, so is no longer valid after the function returns. The space becomes available for use by other code and many be modified - any attempt to access it has undefined behaviour.
The point is, it is a pointer that is returned, not a string; in C a strings (and more generally arrays) are not a first-class data types.
Depending on your needs there are a number of valid ways of returning the string data; for example the following is valid:
char* func()
{
static char c[] = "Hey there!";
return c;
}
because here although the local variable goes out of scope the static data is not destroyed or de-allocated, and any reference to it remains valid.
Another alternative is to embed the string in a struct which is a first-class data type:
typedef struct
{
char content[256] ;
} sString ;
sString func()
{
sString c = {"Hey there!"};
return c;
}
Or more conventionally to copy the data to a caller buffer:
char* func( char* buffer )
{
char c[] = "Hey there!";
strcpy( buffer, c ) ;
return buffer ;
}
I have omitted code to mitigate the possibility of buffer overrun above for clarity in this last example, such code is advised.
char* test() {
char* returnValue = "test";
return returnValue;
}
char* test=test();
printf("%s",test);
is it safe to use? is it the same, as
char* test {
char* returnValue=strdup("test");
return returnValue;
}
char* test=test();
printf("%s",test);
if yes, then should I free it later on? they are both seem to work correctly.
is it the same
No, it isn't.
char * test1() {
char * returnValue = "test";
return returnValue;
}
The above code returns the fixed address to the constant literal "test". This will be the same address each time the function is called.
It is not a dynamical allocation of memory.
Doing
printf("%d\n", test1() == test1());
will print
1
meaning "true", the two addresses returned are the same.
On "constness"
To better reflect the constness of the result of test1() it should better be defined as follows:
const char * test1() {
const char * returnValue = "test";
return returnValue;
}
char * test2 {
char * returnValue = strdup("test");
return returnValue;
}
The above code returns the address to a freshly allocated area of memory having been copied "test" into. This will be a different*1 address each time the function is called.
*1: "different" at least, as long as the result of any previous call to test2() had not been free() ed already
This is a dynamical allocation of memory. It therefore requires a call to free() passing in the address returned by strdup() (which internally calls malloc()) to deallocated the memory, if not needed any more.
Doing
printf("%d\n", test2() == test2()); /* leaks memory: 2 times 4+1 char */
will print
0
meaning "false", the two addresses returned are different.
For completeness: To avoid the leak as per the above snippet do
char * p, * q;
printf("%d\n", (p = test2()) == (q = test2()));
free(p);
free(q);
is it saft to use
Formally the code of both snippets is correct.
Which one to use and if the use if "safe" completely depends on the use case, on the the context.
char* test() {
char* returnValue = "test";
return returnValue;
}
is it safe to use?
Yes, as long as you are not trying to modify the returnValue which is a string literal. The string literals have static storage duration, so they are alive throughout the lifetime of the program but attempt to modify the content of string literal is undefined behavior.
is it the same, as
char* test {
char* returnValue=strdup("test");
return returnValue;
}
Answer is - No
strdup()
Returns a pointer to a null-terminated byte string, which is a duplicate of the string pointed to by str1. The returned pointer must be passed to free to avoid a memory leak.
The strdup() uses malloc() to obtain memory for the new string, here the new string is "test". It stays allocated until it is explicitly deallocated or until the program ends. So, it should be freed using free() once you are done with it. Also, you can modify the content of string returned by strdup() but make sure to not to access beyond the allocated memory chunk.
is it safe to use?
Yes, unless you try to change the string. There is no allocation in fact, so each time your function will return exactly the same pointer to the same location in memory.
is it the same, as
No, the strdup() makes an allocation and returns new allocated memory.
if yes, then should I free it later on?
It is no, but still you need to free the memory after strdup() later on.
they are both seem to work correctly
For printf() it is fine, unless you try to change those strings... You will not be able to change the char* returnValue = "test" string, but you will be able to change the string after strdup()
In both cases, "test" is allocated in the Stack as a read-only portion of memory (const char).
In the first block, you return a pointer to "test". As said before, this will be always the same value across calls to the function. Due to its read-only property, trying to free or modify it, will raise an execution error (munmap_chunk(): invalid pointer when trying to free, Segmentation fault when trying to modify).
In the second block, you return a pointer to a dynamically allocated portion of memory in the Heap. It's your responsibility to free this portion of memory using free() or equivalent. You are free to modify this variable, or even reallocate this portion of memory.
You can always do your own tests:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* test1() {
char* returnValue = "test";
return returnValue;
}
char* test2() {
char* returnValue = strdup("test");
return returnValue;
}
int main(void)
{
char* vtest1 = test1();
printf("%s => %p\n", vtest1, &vtest1);
char* vtest2 = test2();
printf("%s => %p\n", vtest2, &vtest2);
printf("Freeing 2nd test...\n");
free(vtest2);
printf("Trying to modify 1st test...\n");
vtest1[0] = 'p';
printf("Freeing 1st test...\n");
free(vtest1);
return 0;
}
Sample program:
#include <stdio.h>
#include <malloc.h>
void f(int n) {
char *val = (char *) malloc(12*sizeof(char));
val = "feels....";
printf("%s", val);
// free val; // if enable, compile time error: expected ';' before 'val' free val;
}
int main()
{
f(1);
return 0;
}
Is it required to free the memory which is dynamically allocated ? if yes, how to.
Yes, you need to free the memory. But when you allocate memory for a string, the way to populate the string is not to assign a string to it as that replaces the memory you've allocated. Instead you're meant to use the function strcpy like this...
char *val = malloc(12*sizeof(char));
strcpy(val,"feels....");
printf("%s", val);
free(val);
Instead of this:
char *val = (char *) malloc(12*sizeof(char));
val = "feels...."; // val points now to the string literal ""feels...."
// discarding the value returned by malloc
...
free(val); // attempt to free the string literal which will
// result in undefined behaviour (most likely a crash)
you probably want this:
char *val = malloc(12*sizeof(char)); // in C you don't cast the return value of malloc
strcpy(val, "feels...."); // the string "feels...." will be copied into
// the allocated buffer
...
free(val); // free memory returned previously by malloc
The compilation problem is because free is a function, you need to put its argument in parentheses.
free(val);
The other problem is a memory leak.
Strings in C are really just pointers to (hopefully) blocks of memory containing char data. The end of the string is denoted by a char with value 0. The thing to remember is that your variable is simply a pointer like any other pointer. So...
char *val = (char *) malloc(12*sizeof(char));
The above line dynamically allocates a block of memory and assigns a pointer to it to val.
val = "feels....";
The above line assigns a pointer to a string literal to val overwriting the previous pointer that was in val. It has not touched, in any way, the block of memory that was malloced in the first line. Furthermore, you have lost any reference you had to the malloced block so it has leaked. There's no way to free it.
String literals are usually created at compile time and the memory they occupy will be part of the program. This means they haven't come from the heap (where malloc gets its memory from. This means, in turn, when you try to free a string literal, bad things happen. On modern architectures, the program text is protected from writes at the OS level so trying to free part of it will almost certainly crash your program.
As long as you do not want to change the content of the string, you do not need to malloc space to it. You can omit the malloc line (and the corresponding free) and your program will still work.
f you do want to change the string, the easiest way to get a mutable copy of a string literal is to use strdup:
char *val = strdup("feels....");
// Do stuff with the string
free(val); // strdup strings need to be freed
strdup is a Posix function but not a C standard function so your platform might not have it. It's pretty simple to implement your own, though.
char* myStrDup(const char* thingToDup)
{
char* ret = malloc(strlen(thingToDup) + 1); // strlen returns the length without the terminating nul. Hence add 1 to it to allocate
strcpy(ret, thingToDup); // Copies the entire string including the terminating nul.
return ret;
}
I used this code to print some string,but it does not print any thing.What is the problem?
char* getNotFilledEncryptionParams(void)
{
char* nofilledStr;
char tmp[3];
const char * arr[]= {" P,"," Q,"," A,"," B,"," C,"," R,"," S0,","S1,","S2,","F1,","G1"};
for(i=0;i<11;i++)
{
if(filledParams[i] == 0)
{
strcpy(tmp,arr[i]);
strcat(nofilledStr,tmp);
}
}
return nofilledStr;
}
Usage:
int main(void){
char *remaining;
remaining = getNotFilledEncryptionParams();
printf("\r\n Remaining item:%s",remaining);
}
I think the problem is in const char * arr[] and I changed it,but the problem remains.
You didn't allocate any memory for noFilledStr, so its value is indeterminate and strcat(noFilledStr, tmp) is undefined.
Use malloc to allocate memory and initialize noFilledStr with the returned pointer:
char* noFilledStr = malloc(number_of_bytes);
The strings in arr are char[4], not char[3] (do not forget the null byte!). tmp is too small to hold them, so strcpy(tmp, arr[i]) writes out of bounds.
You are trying to build the string to return in the location pointed to by nofilledStr but this pointer is pointing somewhere as you do not initialize it. You could use a sufficiently large static char[] array if you do not have to deal with multiple threads. Otherwise, use malloc() and require the caller to free() the returned string when he is done with it.
Could you please help me? My code does tokenizing, so I created code like this:
I allocate some memory,
I strcpy(malloced_memory, argv)
I execute strtok(mallocted_memory, ".")
Try free(mallocted_memory).
filename = malloc(strlen(argv));
strcpy(filename, argv);
strk_ptr = malloc(sizeof(filename));
strk_ptr = strtok(filename,".");//
i++;
sprintf(in->file_name,"%s",strk_ptr);
while(strk_ptr = strtok(NULL,"."))//
{
i++;
sprintf(in->file_name,"%s.%s",in->file_name,strk_ptr);
sprintf(in->file_ext ,"%s",strk_ptr);
}
free(strk_ptr);
free(filename);
That code has the problem that I can't free(filename). If I try free(filename), then program get SIGTRAP. But program is working.
I want fix that problem. What should I do?
This line:
filename = malloc(sizeof(argv));
should be this:
filename = malloc(strlen(argv) + 1); /* +1 for the '\0' at the end */
if (filename == NULL) { /* take some action */ }
And this line:
strk_ptr = malloc(sizeof(filename));
is only creating a memory leak since it is followed by:
strk_ptr = strtok(filename,".");
And you should check the return value:
strk_ptr = strtok(filename,".");
if (strk_ptr == NULL) { /* take some action */ }
BTW, the strtok() function returns a pointer to a token inside the string passed in the initial call to it (filename in your example). It does not allocate memory, so its return value should NOT be freed (which your program avoids, but it's a common mistake). While I'm grousing about strtok(), I'll mention that you can't (directly or indirectly) pass it a literal string to tokenize, since it modifies the string and literal strings are readonly. That is, doing: strtok("sample.txt", ".") is a no-go.
And finally, this kind of implicit condition is not great form:
while (strk_ptr = strtok(NULL,".")) { ... }
Better is:
while ((strk_ptr = strtok(NULL,".")) != NULL) { ... }
You don't need to allocate memory when using strtok()
There is no problem in freeing filename as it is correctly allocated by malloc(), however there are many other problems and memory leaks.
Basically you first allocate memory for str_ptr:
strk_ptr = malloc(sizeof(filename));
Here malloc() return a pointer which is stored in strk_ptr.
And then you call strtok() which also return a pointer, inside filename:
strk_ptr = strtok(filename,".");
So you lost the original pointer returned by malloc() and now strk_ptr points somewhere in filename. When you call free(str_ptr) you are freeing a memory inside filename. The subsequent call to free(filename) report the error. The solution is simply that don't need to allocate memory for strk_ptr.
I wrote a working minimal code to show you how to correctly use strtok. Please remember that, when asking a question, posting a minimal working code is alway better.
int main(int argc, char **argv) {
char *strk_ptr;
char *filename = malloc(strlen(argv[0]) + 1);
strcpy(filename, argv[0]);
printf("filename = %s, size = %zu\n", filename, sizeof(filename));
// Do not malloc this
//strk_ptr = malloc(strlen(filename) + 1);
strk_ptr = strtok(filename,".");//
printf("%s\n", strk_ptr);
while( (strk_ptr = strtok(NULL,".")) )
{
printf("%s\n", strk_ptr);
}
free(filename);
return 0;
}
First of all argv is a char** so if you want to copy the content of the first argument passed as input you have to use argv[0], which is always the executable file name.
then, sizeof(filename) returns the size of the pointer not the size of the content as filename is not an array. you have to use strlen(filename) + 1.
strtok return a pointer inside the object (filename) which is already allocated so you don't need to allocate memory for strk_ptr.
When using strtok in a loop consider to take the following approach:
for (strk_ptr = strtok(filename, "."); strk_ptr; strk_ptr = strtok(NULL, "."))
{
printf("%s\n", strk_ptr);
}
filename = malloc(strlen(argv));
strk_ptr = malloc(sizeof(filename));
strk_ptr gets some memory, which you then go leave dangling by pointing strk_ptr to filenames memory, you then end up double freeing filename.
So don't malloc strk_ptr. Just leave it as char* then only free filename at the end
strk_ptr = malloc(sizeof(filename));
strk_ptr = strtok(filename,".");//
...
free(strk_ptr);
Doesn't work. At first, strk_ptr points to the malloc'd memory but then the pointer is immediately overwritten with some other value, so basically you lose the pointer to the malloc'd memory and hence cannot free that memory any more.
Edit:
Seeing malloc(sizeof(filename)), I should add that you do not have to allocate memory for the pointer variable itself. The declaration char* strk_ptr; makes the compiler implicitly allocate memory for that pointer (i.e. 4 or 8 bytes). So you can just use the pointer directly like any other variable, and you won't have to free that variable's memory.
char* strk_ptr;
strk_ptr = strtok(filename,".");
Or, if that wasn't your intention then note that sizeof(filename) does not return the length of the string, but just the size of the pointer variable filename, i.e. usually 4 or 8, independent of what string filename points to. See also http://www.gnu.org/software/libc/manual/html_node/String-Length.html:
char string[32] = "hello, world";
char *ptr = string;
sizeof (string)
⇒ 32
sizeof (ptr)
⇒ 4 /* (on a machine with 4 byte pointers) */