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.
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.
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'm writing a C program but i'm getting some memory errors so i decided to make a small program to see when and how to deallocate memory.
My example :
int main() {
char *a=malloc(5);
a="mama";
char *b=malloc(strlen(a));
printf("%s\n",a);
strcpy(b,a);
free(a);
printf("%s\n",b);
return 0;
}
here i'm getting an error :
* Error in `./a': free(): invalid pointer: 0x0000000000400757 *
but when i change just one line :
int main() {
char *a=malloc(5);
strcpy(a,"mama");
char *b=malloc(strlen(a));
printf("%s\n",a);
strcpy(b,a);
free(a);
printf("%s\n",b);
return 0;
}
My second program is working well, so why i'm getting this error in the first?
i hope that you can explain me why.
In My Real program I'm doing like that :
char * getDate(){
char *date=malloc(5);
//some instructions here
return date;
}
int main() {
char *a=malloc(5);//im sure that a will not exceed 5 bytes
a=getDate();
return 0;
}
It's just a small example , and i don't know where to free memory .so how and where i can free memory , have I to free date or the char pointer?
Edited second Time:
void getDate(char *a){
//some instructions here
strcpy(a,"haha");
}
int main() {
char *a=malloc(5);
getDate(a);
int i= strlen(a);
printf("%s and the size is :%d\n",a,i);
free(a);
return 0;
}
what are the rules i have to follow to avoid memory errors.
many thanks.
In the line:
char *a=malloc(5);
You assign a with the address of a dynamically allocated memory block, but then in the line:
a="mama";
You reassign it with the address of the literal string constant "mama". Discarding the pointer to the dynamically allocated block so that when you call
free(a);
a is no longer a valid heap memory block, and cannot be deallocated.
Strings (and arrays in general) in C are not data first-class types and cannot be assigned. You should replace:
a="mama";
with
strcpy( a, "mama" ) ;
The assignment sets the pointer value - it does not copy "mama" to the memory points to by a. The strcpy() call on teh other hand copies the string to the dynamic memory block referenced by a.
In your second code fragment, you are "leaking" the memory allocated in main() since you have reassigned a without freeing the original block. Although in your example you have not free'd a, it remains freeable, because the allocation in GetDate() is dynamic. As a coding style, dynamically allocating memory in a function and returning its pointer is a bad idea since it makes it the responsibility of the caller to know that the memory was dynamically allocated and must be free'd, and it invites memory leaks.
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.
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;
}