how to free memory in C - c

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.

Related

Segmentation fault when trying to free memory

I have below code where I have commented when I get segmentation fault and when not.
Originally I got segmentation fault and then I could figure out that probably I cannot initialize my char pointer locations like "abcd". But I am not able to understand - WHY?
I thought testString = "abcd"; will put a at first memory address, b at second and so on ...
Segmentation fault occurs when trying to free memory, based on how I initialize memory location.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char* testString = malloc(sizeof(char) * 5);
printf("Size of char is: %d\n", sizeof(char));
printf("Size of int is: %d\n", sizeof(int));
for(int i = 0; i < 5; i++)
{
printf("Pointer addresses are: %p\n", testString + i);
}
char* tempPtr = testString + 2;
printf("My temp pointer address = %p\n", tempPtr);
// This gives me segmentation fault ....
testString = "abcd";
// This will not give me segmentation fault ....
//int count = 65;
//for(int i = 0; i < 5; i++)
//{
// testString[i] = count + i;
//}
printf("Printing character...\n");
for(int i = 0; i < 5; i++)
{
printf("Characters are: %c\n", testString[i]);
}
printf("Freeing memory...\n");
free(testString);
//printf("Access after freeing >>%c<<\n", tempPtr[0]);
//free(testString);
}
Based on #M.M. and #Jonathan's comment I understood that with testString = "abcd"; my testString will point to a memory location where string "abcd" was created and since I didn't malloc'ed it I cannot free it. Also, since my original pointer to heap memory (which I got using malloc) is gone, so it is waste of memory or memory lead.
So, does it means that when I use printf statement like printf("Printing character...\n");, this is also a memory leak? Then how do I avoid it? Looping and inserting into char* is certainly a bad idea.
this line:
testString = "abcd";
is overlaying the pointer given by the call to malloc() with the address of the string literal: "abcd" this results in a memory leak because the original pointer to the allocated memory is lost.
In C, when copying a string, it 'should' be handled by the functions: strcpy() and strncpy() which will not corrupt the pointer contained in testString.
strcpy( testString, "abcd" );
strncpy( testString, "abcd", strlen( "abcd" ) );
Naturally, once the pointer to the allocated memory has been overlayed/destroyed by the assignment statement: testString = "abcd";, the new value placed into testString must not be passed to free()
the seg fault would be happening at the call to free(), not at the incorrect assignment of a new pointer to testString.
Using printf is not a memory leak. Memory leaks occur when a pointer is allocated via malloc [or, herein, strdup] and there is no corresponding free call for it.
Also, trying to free a pointer that has not been allocated is another type of error. It [probably] won't segfault, but free will complain.
Here's a simplified version of your program that illustrates some of the ways you can do this:
#include <stdio.h>
#include <string.h>
#include <malloc.h>
int opt_segv;
char *temp = "abcd";
void
dostr(char *str,int modflg)
{
printf("\n");
printf("dostr: %s\n",str);
if (modflg)
str[modflg] = 'm';
printf("dostr: %s\n",str);
}
void
test1(void)
{
int len;
char *testString;
len = strlen(temp);
testString = malloc(len + 1);
strcpy(testString,temp);
dostr(testString,1);
free(testString);
}
void
test2(void)
{
char *testString;
testString = strdup(temp);
dostr(testString,2);
free(testString);
}
void
test3(void)
{
char *testString;
// passing a pointer to a string _constant_ -- do _not_ modify
testString = temp;
dostr(testString,opt_segv ? 3 : 0);
}
int
main(int argc,char **argv)
{
char *cp;
--argc;
++argv;
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
case 's': // generate segfault
opt_segv = 1;
break;
}
}
test1();
test2();
test3();
return 0;
}
You can run the program with -s to simulate the string constant modification that caused your segfault.
This question has content relevant to answer of my question but doesn't have detailed answer. #Jonathan's comments answers all my questions but he hasn't put forward a detailed answer so I am writing my answer so that folks who will visit further can have detailed explanation:
I created a pointer and allocated some space on "heap segment" of the memory, now my pointer was pointing to that memory location on heap.
Code relevant for all this is - char* testString = malloc(sizeof(char) * 5);.
Now, when I dis this - testString = "abcd"; then string "abcd" is created in "text/code segment" (or in some implementation data segment) of the memory and memory address is returned and assigned to my pointer testString.
What happens is that my original pointer which was pointing a memory location on heap is lost and the pointer started pointing to a memory location on text/code segment of the memory.
Implication of all this:
It has resulted in memory leak because my original pointer which was pointing to the heap memory is lost, so now I have no way to free that heap memory and hence memory leak.
When I will try to free that memory using free(testString); then I will get segmentation fault (this is exactly what has happened to me) because free() can only be used to free the memory which is allocated using either malloc, calloc or realloc. Now, since the pointer testString is pointing to a memory location on text/code segment and I had not allocated that memory using some C memory allocation method, so I cannot free it using free() and if I do so then I get segmentation fault.
When I do testString = "abcd" (when testString is a pointer) then I cannot access the memory location pointed by testString because the memory allocated is read-only in text/code segment of the memory. So, testString[0] = 'x' will also result in segmentation fault.
What happens when I do printf("hello, world")?:
This will create "hello, world" string as read-only in text/code segment of memory. I verified that it does create in text/code segment in C99 implementation using size command.

realloc() invalid old size

I am doing an exercise for fun from KandR C programming book. The program is for finding the longest line from a set of lines entered by the user and then prints it.
Here is what I have written (partially, some part is taken from the book directly):-
#include <stdio.h>
#include <stdlib.h>
int MAXLINE = 10;
int INCREMENT = 10;
void copy(char longest[], char line[]){
int i=0;
while((longest[i] = line[i]) != '\0'){
++i;
}
}
int _getline(char s[]){
int i,c;
for(i=0; ((c=getchar())!=EOF && c!='\n'); i++){
if(i == MAXLINE - 1){
s = (char*)realloc(s,MAXLINE + INCREMENT);
if(s == NULL){
printf("%s","Unable to allocate memory");
// goto ADDNULL;
exit(1);
}
MAXLINE = MAXLINE + INCREMENT;
}
s[i] = c;
}
if(c == '\n'){
s[i] = c;
++i;
}
ADDNULL:
s[i]= '\0';
return i;
}
int main(){
int max=0, len;
char line[MAXLINE], longest[MAXLINE];
while((len = _getline(line)) > 0){
printf("%d", MAXLINE);
if(len > max){
max = len;
copy(longest, line);
}
}
if(max>0){
printf("%s",longest);
}
return 0;
}
The moment I input more than 10 characters in a line, the program crashes and displays:-
*** Error in `./a.out': realloc(): invalid old size: 0x00007fff26502ed0 ***
======= Backtrace: =========
/lib64/libc.so.6[0x3d6a07bbe7]
/lib64/libc.so.6[0x3d6a07f177]
/lib64/libc.so.6(realloc+0xd2)[0x3d6a0805a2]
./a.out[0x400697]
./a.out[0x40083c]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x3d6a021b45]
./a.out[0x400549]
I also checked realloc invalid old size but could not follow the logic of passing a pointer to a pointer to the function modifying the array.
realloc call will re-allocate memory by taking a pointer to a storage area on the heap i.e a dynamically allocated memory result of a call to malloc.
In your case the problem is that you are allocating memory on the stack and not dynamically by a call to malloc which results memory allocation on the heap. And, passing the pointer of the automatic character array line to _getline which uses it for call to realloc. So, you got the error.
Try dynamically allocating the character array line :
char* line = (char *) malloc(MAXLINE);
char* longest = ( char *) malloc(MAXLINE);
You get an invalid old size error when your code writes the memory that malloc/realloc allocated for "housekeeping information". This is where they store the "old" allocated size. This also happens when the pointer that you pass to realloc has not been properly initialized, i.e. it's neither a NULL nor a pointer previously returned from malloc/calloc/realloc.
In your case, the pointer passed to realloc is actually an array allocated in automatic memory - i.e. it's not a valid pointer. To fix, change the declarations of line and longest as follows:
char *line = malloc(MAXLINE), *longest = malloc(MAXLINE);
To avoid memory leaks, make sure that you call free(line) and free(longest) at the end of your program.
You are trying to realloc() memory that was not allocated dynamically with malloc(). You cannot do that.
Also, if realloc() fails, the original memory is still allocated, and thus still needs to be freed with free(). So do not assign the return value of realloc() to the original pointer unless it is not NULL, otherwise you are leaking the original memory. Assign the return value of realloc() to a temp variable first, check its value, and then assign to the original pointer only if realloc() was successful.
if _getline() reads 10 or more characters, it will call realloc() on memory that was not allocated with malloc(). This is undefined behavior.
Additionally, the memory allocated from realloc() will be leaked at the end of the call to _getline().
Additionally, let's assume that the input string is "0123456789\n". Then you will attempt to write to longest that value, but you will never call realloc() before you do that, which is required.
Your error is here:
int _getline(char s[])
It means _getline is a function returning int getting a pointer to char by value.
You actually want to pass that pointer (which must point to memory allocated with malloc() or be NULL) by reference.
That means, you need to pass a pointer to a pointer to char.
Correcting that error will force you to correct all follow-on errors too.
Only use free / realloc on NULL resp. on pointers returned from malloc, calloc, realloc or a function specified to return such a pointer.

Using free() on static array of char*

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.

ERROR READING STRING

My code does not work. I get run time error at the moment i accept a string. What is the problem with this code?
//this is what i have in main()
char *ele,*s[max];
int *count,temp=0;
count=&temp;
printf("Enter string to insert: ");
scanf("%s",ele);
addleft(s,ele,count);
//following is the function definition
void addleft(char *s[max],char *ele,int *count)
{
int i;
if((*count)==max)
{
printf("Queue full!\n");
return;
}
for(i=*count;i>0;i--)
strcpy(s[i],s[i-1]);
strcpy(s[0],ele);
(*count)++;
printf("String inserted at left!\n");
}
ele is an uninitialised char* and has no memory associated with it and scanf() will be attempting to write to it causing undefined behaviour, a segmentation fault is probable.
You need to either dynamically allocate memory for ele or declare a local array and prevent buffer overrun when using scanf():
char ele[1024];
if (1 == scanf("%1023s", ele))
{
/* Process 'ele'. */
}
Additionally, the function addleft() is using strcpy() on s, which is an array of char* and each of the char* in the array is unitialised. This is undefined behaviour and a probable segmentation fault. To correct, you could use strdup() if it is available otherwise malloc() and strcpy():
/* Instead of:
strcpy(s[0],ele);
use:
*/
s[0] = strdup(ele);
Note that the for loop inside the addleft() function is dangerous as the char* contained within s are not necessarily of the same length. This could easily lead to writing beyond the end of arrays. However, as the elements are addresses of dynamically allocated char* you can just swap the elements instead of copying their content.
sscanf("%s", ele) is putting the input in the memory pointed to by 'ele'. But 'ele' has never been initialized to point to anything. Something like:
char ele[128];
or
char* ele = malloc(...)
should fix it up.
You are causing a buffer overflow because the pointer ele is not pointing to any allocated memory. You are writing into memory that your program needs to run, therefore crashing it. I recommend you implement mallocinto your program like this:
char *ele;
if (!(ele = malloc(50))) //allocate 50 bytes of memory
{
//allocation failed
exit(0);
}
scanf("%s", ele); //string can hold 50 bytes now
free(ele); //free allocated space
You might want to read up on the malloc function here
An easier route would just to make ele an array instead of a pointer:
char ele[50]; //ele is an array of 50 bytes

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