free memory if pointer redirects - c

I've some trouble understanding how to free my memory correctly in following codesnippet:
char *func(char* s){
/* do something with s */
// pass s to function, create new string, return this string
s = function_allocating_mem(s);
// pass s to function, create new string, return this string
s = other_function_allocation_mem(s);
/* do other stuff again */
return s;
}
int main(void){
char str[] = "somestring";
str = func(str);
}
Now I allocated different sizes of memory two times. But if I get it right, I just change the pointer address and never free the memory.
I don't really know, what to google to find an example
Is that correct and how would I change it?
EDIT:
I removed the second parameter of the function. It was not necessary and confusing.

When you allocate memory from the heap in your program, you have to have a clear understanding of:
Where memory from heap is allocated in your program.
How the ownership of heap allocated memory is transferred from one function to the next, and
Where it is deallocated before the program ends.
In your case, assuming function_allocating_mem and other_function_allocation_mem don't call free on the input argument, you have to make sure that the memory allocated in those functions is deallocated in either fun or main.
char *func(char* s, const char* os){
char* s1 = NULL;
char* s2 = NULL;
/* do something with s and os */
// pass s to function, create new string, return this string
s1 = function_allocating_mem(s);
// pass s to function, create new string, return this string
s2 = other_function_allocation_mem(s1);
/* do other stuff again */
// Deallocate memory that was allocated by function_allocating_mem().
free(s1);
// Memmory allocated by other_function_allocation_mem is returned to the
// calling function.
return s2;
}
int main(void){
char str[] = "somestring";
// This is not legal anyway.
// str = func(str, "some other string");
char* s = fun(str);
// Use s ...
// Before returning from this function, deallocate memory
// that was allocated in the call to fun().
free(s);
}

In code You've provided, correct way to free memory would be:
char *s2;
s2 = other_function_allocation_mem(s);
free( s );
s = s2;
...
free( s );
return ns;

So many problems.
1. You declared that func takes two parameters. Then you only called it with one param.
2. You declared that func returns a char*, then you try to assign that to a char[].Arrays and pointers are related, but they are not interchangable.
3. In func, you never use param os.
4. You return variable ns. It was never declared.

Related

Allocating memory for strings dynamically

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;
}

how to free the dynamically allocated memory for a local variable?

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;
}

when to carefully use free() to free up malloc() used memory?

I read from many question here in SO and some other articles regarding free() function in c that frees the memory of unused variables. In my case, I have the following code block.
char *injectStrAt(char *str, char *strToIn, int pos)
{
char *strC = malloc(strlen(str) + strlen(strToIn) + 1);
strncpy(strC, str, pos);
strC[pos] = '\0';
strcat(strC, strToIn);
strcat(strC, str + pos);
return strC;
}
The above function I use to inject a string block in to an array. I am using malloc to create a new char*. In the above case do I need to do free(strC) ? advice pls.
strC is the return value of this function, so you don't call free(strC) inside the function itself. You need to free it outside the function, the time when this string is not used anymore.
Since your function is returning strC, one presumes it must remain valid after the return of this function, thus this function must not free() that buffer. Once it's freed, the buffer is no longer valid so must not be used.
Your caller is responsible for freeing it in this case.
No you shouldn't free strC inside this function because it is the return value of this function. If you do so the statement:
return strC;
will return some unexpected or garbage value.
char* stringA = injectStrAt(str, strToIn, pos);
printf("StringA: %s"); // unexpected value.
So when should you free up the memory? Well, you should do it after the value of strC is returned from the function injectStrAt() to stringA, in this particular case. Although generally memory is freed when the string or the variable to which the memory was allocated is no longer required.
char* stringA = injectStrAt(str, strToIn, pos);
/... use the string
free(stringA);

Better way to return the value from a function

#include<stdio.h>
char* my_strcpy(char* source, char* destination) {
char* p = destination;
while( *source != '\0' ) {
*p++ = *source++;
}
*p = '\0';
return destination;
}
int main() {
char stringa[40] = "Time and tide wait for none";
char stringb[40];
char *ptr;
char *ptr1;
ptr = stringa;
ptr1 = stringb;
puts(stringa);
puts(ptr);
my_strcpy(ptr, ptr1);
puts(ptr);
return 0;
}
Here the variable destination, as the local copy of the function, is returning the pointer is safe. I believe it will be safe as long as the address is used immediately after returning or else what if some other process uses the address, it will be changed.
How to return safely without doing return destination?
Is it possible to do a malloc for p and return it rather than assigning the location pointed by destination?
destination isn't controlled by my_strcpy, so what happens to it outside of the function is irrelevant to my_strcpy. That is to say, it's perfectly safe and expected for the function to return destination. Whoever called my_strcpy will be responsible to make sure the variable's memory is ok. Returning the destination variable is simply a convenience for function chaining.
You could malloc and return a new area of memory (though then you wouldn't need a destination parameter). This is basically the functionality of strdup, and it's the responsibility of the caller of strdup to free the memory that was allocated.
Note, there's no risk of another process corrupting the memory. Unless you're dealing with shared memory, processes each have access to only their memory. Some function later on in this process could change what you did in my_strcpy, but that's not the problem of my_strcpy. As for it being safe if it's used immediately after the function, you're copying into space that was assigned to you. The p value isn't the memory you're writing into; it's just the pointer to the memory. And the memory itself isn't on the stack. As jpw mentioned at some point - you don't need the p variable at all.

How to clear a char* passed to a function in C?

How can i make a function to clear a C string and/or free the allocated memory? Why the following code does not work?
void freeStr(char** str) {
free(*str);
}
int main() {
char* str = "some string";
freeStr(&str);
printf("%s", str);
return 0;
}
You can neither free nor clear the memory of the array that a string literal denotes.
However, to lose access to it, all you need is to change the pointer you've stored its address in:
str = NULL; // in main
// or
*str = NULL; // in freeStr
You might find it helpful to go over the C FAQ - malloc section.
As others have noted, you can't free or modify string literals as they are usually placed in read only sections of memory. However, if you wish to clear and free() dynamically allocated memory, you'd do something like the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LENGTH 20
void freeStr(char **str)
{
free( *str );
*str = NULL;
}
int main() {
char *str = malloc( sizeof(char) * LENGTH);
// clear that allocated memory
memset( str, 0x00, LENGTH );
// Put some text into the memory
strncpy( str, "Some text", LENGTH-1 );
printf("Before: %s\n", str);
freeStr(&str);
// string is now NULL and the memory is free.
printf("After: %s\n", str);
return 0;
}
The string you allocated is in the CONST_DATA section (cannot be modified) and hence, you cannot call free on it.
That part of memory is allocated at compile time and is read only. That part of memory still holds "some string\0"
The CONST_DATA section, in assembly is like the data-segment (DS), which contains global and static (read-only) variables initialized at compile time itself. They do not change during runtime, and remain allocated to the running program.
The answers are pretty good, but there are a few points that they've missed or omitted.
Your question is also slightly vague.
If you want to clear a C string you overwrite the memory space that it points to with null bytes. You can only free() a C string that has been allocated by the heap allocator via a call to one of the heap allocator functions such as malloc(), calloc() or realloc() etc.
So if you allocated a string using malloc(), or one of the other heap allocation functions, like so and then copied a string into it, you could clear it by calling memset(), but you would still then have to call free() to release that memory back to the heap.
For example:
char* strPtr = malloc(32); // allocate 32 bytes of storage off the heap
strcpy(strPtr, "test"); // copy a string into the newly allocated block on the heap
memset(strPtr, 0, 32); // clear the allocated block
free(strPtr); // return the allocated block to the heap
Also, note that C uses block scope and you do not have to explicitly deallocate arrays which were declared with the default storage class, auto, as they are popped off of the stack frame when that block goes out of scope.
void foo() {
char strArray[32]; // this is a stack allocation
strcpy(strArray, "test"); // copy a string onto the stack
return; // no call to free() required
}
Finally, yet another method of allocation is static. When you use the declaration:
char* str = "literal string";
The space for the string "literal string" resides in a statically allocated segment which should never be written to. On some platforms, you will get a segfault if you try to write to that memory segment. You should not attempt to clear memory blocks that were statically allocated as there is no guarantee that the segment which they are mapped into is writable.
http://en.cppreference.com/w/c/memory/free
void free( void* ptr );
Deallocates the space previously allocated by malloc(), calloc() or realloc(). If ptr is null-pointer, the function does nothing.
Your string is not allocated with any of these functions. I think is this way.
void freeStr(char **str) {
*str = NULL;
}
int main() {
char* str = (char *)"some string";
printf("Before: %s\n", str);
freeStr(&str);
printf("After: %s\n", str);
return 0;
}

Resources