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;
}
Related
I can tell that there will be a memory leak on this and am looking for improvements / the standard way of doing things as far as these kind of problems go.
(e.g. how an experienced / pro use on C would implement this)
This is a simple case switch programme. Its purpose is to give it PizZa and give you back pIZza.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char changeCase(char ch){
if ( (int)ch < 65 || (int)ch > 122){
return ch;
}else if ((int)ch < 91){
return (char)(ch + 32);
}
else{
return (char)(ch - 32);
}
}
char* toUpper(char* string){
size_t size=strlen(string);
char* temp = (char*) malloc(size);
while (*string != '\0'){
*temp = changeCase(*string);
temp++;
string++;
}
return (temp - size);
}
int main() {
char* string = toUpper("PIZa");
printf("%s",string);
return 0;
}
This results in a memory leak since the memory from malloc is not freed. What would be better? Allocating memory outside the function and giving the pointer to that memory to the toUpper function? Other idea?
The de facto standard rule is that the part of the code that did the dynamic allocation is also responsible for freeing it. So if your function was in some file "toupper.c", then there should have been some manner of clean-up function available in that same C file.
However, the best solutions separates memory allocation and algorithms. This means that a better way to write this function is this:
void toUpper (char* dst, const char* src)
{
while (*src!= '\0')
{
*dst= ...
...
dst++;
src++;
}
}
Here, the caller can allocate space for dst as it pleases, it's no business of the algorithm. For example:
char str1[] = "hello world";
char* str2 = malloc(strlen(str1) + 1);
toUpper(str2, str1);
...
free(str2);
Just make sure to document the function so that the caller knows that they have to allocate space for dst - to be at least as large as src.
As a side-note, char* temp = (char*) malloc(size); is wrong, you didn't allocate room for the null terminator. Also your algorithm must make sure to copy the null terminator into the destination buffer.
This results in a memory leak since the memory from malloc is not freed.
Actually there is no memory leak in your code. All allocated memory will be freed when the program terminates.
A memory leak occurs in a running program when the program no longer holds a pointer to the allocated memory.
Example:
int main() {
char* string = toUpper("PIZa");
printf("%s",string);
string = toUpper("BRead"); // This causes a memory leak because after this
// line there is no longer any pointer to the
// memory allocated in the first call of toUpper
string = NULL; // Again this causes a memory leak because after this
// line there is no longer any pointer to the
// memory allocated in the second call of toUpper
return 0;
}
Note: Even leaked memory will be freed when the program terminates. Memory leaks are (mainly) a problem in "long" running programs.
What would be better? Allocating memory outside the function ...
Well, it's a matter of taste.
As an example: The widely used (but non-standard) strdup function handles allocation inside the function and requires the caller to free the memory later on.
For a function that reads an unknown amount of characters as user input it can also be nice to do malloc (and realloc as needed) inside the function.
There is really no right or wrong here. You are the designer so you decide. It's all about the "function contract", i.e. the documentation of the function - how to call it and what it will do.
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 have the following code:
void fn(char *string , int flag)
{
static char* array_of_strings[100];
static int index = 0;
if(flag)
{
array_of_strings[index] = (char *)malloc(10);
strcpy(array_of_strings[index] , string);
index++;
}
else
{
//How should I deallocate the memory here?
index--;
}
}
What will happen to the array_of_strings[index] if the else block is met? Will it be automatically dealocated or will it stay after fn() returns? Should I be using this line in place of the comment:
array_of_strings[index] = 0;
Or can I use free() like this:
free(array_of_strings[index]);
Will this free the block of memory allocated by malloc?
This is all OK:
/* Allocate an array to hold 100 char * pointers: OK */
static char* array_of_strings[100];
/* Allocate space to hold one 9-character string: OK */
array_of_strings[index] = malloc(10);
/* Free string: OK */
free(array_of_strings[index]);
This will cause you grief:
/* Whoops: step on the pointer, then try to free it. Not good :( */
array_of_strings[index] = 0;
free(array_of_strings[index]);
Q: What will happen to the array_of_strings[index] if the else block
is met? Will it be automatically dealocated or will it stay after fn()
returns?
A: If you malloc something, it will remain allocated until you "free()" it ... or until the program terminates.
A call
free(array_of_strings[index]);
does not deallocate a static array of char*, it deallocates a block of memory reserved for 10 chars that has been allocated dynamically, and a pointer to which has been stored in a static array of pointers. This is the right thing to do to avoid memory leaks.
This line, on the other hand, makes it impossible to access a dynamically allocated block of memory:
array_of_strings[index] = 0;
This situation is commonly known as a "memory leak". You should avoid it.
Note that it is not uncommon to set the freed pointer to zero to avoid dereferencing it accidentally, like this:
free(array_of_strings[index]);
array_of_strings[index] = 0; // Prevent a "dangling reference"
If you do it this way, you can tell that a pointer at array_of_strings[index] is no longer valid at some later time.
I am puzzled by this response.Can anyone help me on this and point out where I am making a mistake? The output at codepad is "memory clobbered before allocated block"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *s = (char *)malloc(10 * sizeof(char));
s = "heel";
printf("%s\n",s);
printf("%c\n",s[2]);
printf("%p\n",s);
printf("%d\n",s);
free(s);
return 0;
}
You're trying to free constant memory with:
free(s); // cannot free constant "heel"
What you're doing is allocating a piece of memory and storing its location (char *s). You are then overwriting that reference with one to a string constant "heel" (memory leak), which cannot be freed. To make this behave as desired, you should be copying the constant string to the memory you allocated:
strcpy(s, "heel");
Here is an example for getting user input:
char *input = malloc(sizeof(char) * 16); // enough space for 15 characters + '\0'
fgets(input, 16, stdin);
// do something with input
free(input);
To expand on #TimCooper's answer:
first you do: char *s = (char *)malloc(10 * sizeof(char));
then: s = "heel";
The first line allocates memory and assigns the location of that memory to s. But the second line reassigns s to the memory location of constant string heel on the stack!
Which means you try and free() memory on the stack, which is illegal. AND you leak memory, since what you first allocated to s is now inaccessible.
If you want to write a string into the memory pointed by s, you should use something like strcpy() (or, better, strncpy()).
You cannot free(s) - it's constant memory.
Try to change s = "heel"; with strcpy(s,"heel");
char *s = (char *)malloc(10 * sizeof(char));
s = "heel";
Doesn't do what you think, or what you would expect with more modern languages
The first line allocates some memory for 10chars and returns the address of it.
The second line changes that address to point to a constant block of memory allocated at compile time, containing "heel" losing the link to the allocated memory - leaking it