Free 2D char array - c

I need to free an array of pointers. So I have set up a simple error prone example of what I am trying to do.
int main() {
char ** strings = malloc(2);
strings[0] = malloc(sizeof(char)*4);
strings[1] = malloc(sizeof(char)*4);
strings[0] = "ABCD";
strings[1] = "EFGH";
free(strings[1]);
}
I believe I need to free the pointers in reverse order so I started with index one.
However I get this error:
free(): invalid pointer: 0x0000000000400d49 ***
Freeing like free(strings); clears index zero, however calling it again throws the error:
double free or corruption (fasttop): 0x00000000008e5010 ***
What is the correct way to wipe out this pointer array? Or if there is something wrong with how I created the array, please let me know.

strings[0] = "ABCD"
replaces the pointer to allocated memory with a pointer to the string literal "ABCD". You didn't allocate memory for this so can't free it.
Use
strcpy(strings[0], "ABCD");
to copy into the memory you allocated.
Note that you'll still have another couple of problems here. First, you need to allocate space for two pointers in your strings array - you currently only allocate 2 bytes. Second, "ABCD" requires 5 bytes of storage (the 5th byte is for the nul terminator). You therefore either need to allocate 5 bytes for each array or, better, combine allocation and string copying using strdup (a Posix rather than C standard function)
char ** strings = malloc(2 * sizeof(*strings));
strings[0] = strdup("ABCD");
strings[1] = strdup("EFGH");

int main() {
char ** strings = malloc(sizeof(char*)*2);
strings[0] = malloc(sizeof(char)*5);
strings[1] = malloc(sizeof(char)*5);
strcpy(strings[0], "ABCD");
strcpy(strings[1], "EFGH");
free(strings[0]);
free(strings[1]);
free(strings);
return 0;
}

This code strings[0] = "ABCD"; is not doing what you expect.
Instead of copying the bytes to the allocated array you get a memory leak. You re-assign strings[0] to point to string literal equal to "ABCD"(thus the allocated array is leaked). That is why calling free on strings[1] fails. What you need to do is use strcpy:
strcpy(strings[0], "ABCD");
strcpy(strings[0], "EFGH");

Related

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

Difference between these two pointer to char initialisations

I know this has been answer before, but I can't find the question.
What are the differences between these two initialisations:
int main()
{
char* pch1;
char* pch2;
pch1 = (char*)malloc(sizeof(char) * 5);
strcpy(pch1, "Text");
pch2 = "Text";
}
First: don't cast the return value from malloc - it's a common source of errors. Do I cast the result of malloc?
pch1 = malloc(sizeof(char) * 5);
assigns a pointer to a dynamically allocated block of 5 bytes on the heap.
pch2 = "Text";
should ideally be avoided because it assigns a pointer to a string literal. String literals are read-only on most OSes and is also a common source of mistakes. If you do this you should make the pointer to const
const char * pch2 = "Text";
There are three main differences here:
The first one copies the content of a string literal into dynamic memory, while the second one points to that literal directly.
Modifying pch1 string is legal; modifying pch2 string is illegal
You need to free pch1 to avoid memory leak.
For completeness, consider pch3 which is initialized like this:
char tmp[] = "Text";
char *pch3 = tmp;
This pch3 is modifiable like your pch1, but it does not need freeing, because the content of the string is copied into automatic memory.
pch1 points to heap
you can modify it within bounderies
plus you have to free it
other points to static data segment
you can not modify it
pch1 will use heap memory for storing your data
pch2 - using stack memory

freeing an double pointer

int size_of_daten = 5;
char *data[size_of_daten];
char *normal_Pointer = (char*)malloc(sizeof(char) * 100);
int i;
for(i=0; i<size_of_daten; i++) {
data[i] = (char*)malloc(sizeof(char) * 100);
}
data[0] = "0";
data[1] = "1";
data[2] = "2";
data[3] = "3";
data[4] = "4";
printf("data[2] %s\n",data[2]);
strcpy(normal_Pointer,data[2]);
for(i=0; i<size_of_daten; i++) {
free(data[i]);
}
free(data);
I just tried this... even I freed the array as I malloced it... also I copied the value of data[2] and didn't point at it... so that shouldn't be the problem...
You're trying to copy the strings "0", "1", etc. into your data array: you can't just use = to copy strings, you'll need to use a string library method like strcpy.
Once you assign to your array elements those literal strings, e.g.: data[0]= "0";
, the array elements no longer point to the memory that you've allocated, they point to memory that doesn't belong to you, and you can't use free. You've lost the references to your memory blocks from malloc, causing a memory leak.
Furthermore, you can't do free(data); because it wasn't allocated using malloc: it's an array allocated on the stack.
This is not how you copy data into an array of chars you've previously allocated:
data[0]= "0";
data[1]= "1";
data[2]= "2";
data[3]= "3";
data[4]= "4";
You're overwriting the pointers with the address of 5 new pointers. At this point you've lost the address of the memory you had allocated, and when you call free you're calling it on the statically allocated string "0".
You need to use strcpy to copy bytes from one character array into another:
strcpy(dest[0], "0");
strcpy(dest[1], "1");
/* etc */
With data[0]= "0" you are overwriting whatever malloced address returned by malloc.
What you should be doing instead is
strcpy(data[0], "0");
strcpy(data[1], "1");
...
First, assignment to the elements of data after allocating leaks the previously allocated memory. When you assign a char *, you assign only the char *: it doesn't copy the string, it overwrites the pointer.
Second, you're freeing data declared on the stack. You define data with:
char *data[size_of_daten];
This describes an on-stack array of character pointers. It will go out of scope when your function returns, and freeing it manually will blow up.

Memory Clobbered

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

error in using realloc in C/C++

char *t = malloc(2);
t = "as";
t = realloc(t,sizeof(char)*6);
I am getting error "invalid pointer: 0x080488d4 *"..
I am getting strange errors in using memory allocation functions. Is there any good tuts/guides which could explain me memory allocation functions.
I am using linux..
Please help..
This is your problem:
char *t = malloc(2);
t = "as";
You probably thought this would copy the two-character string "as" into the buffer you just allocated. What it actually does is throw away (leak) the buffer, and change the pointer to instead point to the string constant "as", which is stored in read-only memory next to the machine code, not on the malloc heap. Because it's not on the heap, realloc looks at the pointer and says "no can do, that's not one of mine". (The computer is being nice to you by giving you this error; when you give realloc a pointer that wasn't returned by malloc or realloc, the computer is allowed to make demons fly out of your nose if it wants.)
This is how to do what you meant to do:
char *t = malloc(3);
strcpy(t, "as");
Note that you need space for three characters, not two, because of the implicit NUL terminator.
By the way, you never need to multiply anything by sizeof(char); it is 1 by definition.
That is not how you assign strings in C.
The correct syntax is:
char* t = malloc(3); // Reserve enough space for the null-terminator \0
strncpy(t, "as", 3);
// Copy up to 3 bytes from static string "as" to char* t.
// By specifying a maximum of 3 bytes, prevent buffer-overruns
Allocating 2-bytes is NOT enough for "as".
C-strings have a 1-byte null-terminator, so you need at least 3 bytes to hold "as\0".
(\0 represents the null-terminator)
The code you wrote: t = "as"; makes the pointer t "abandon" the formerly allocated memory, and instead point to the static string "as". The memory allocated with malloc is "leaked" and cannot be recovered (until the program terminates and the OS reclaims it).
After this, you can call realloc as you originally did.
However, you should not do t = realloc(t,6);. If realloc fails for any reason, you've lost your memory.
The preferred method is:
new_t = realloc(t, 6);
if (new_t != NULL) // realloc succeeded
{ t = new_t;
}
else
{ // Error in reallocating, but at least t still points to good memory!
}
Your code reassigns t, making it point elsewhere
char *t = malloc(2); //t=0xf00ba12
t = "as"; //t=0xbeefbeef
t = realloc(t,sizeof(char)*6); //confused because t is 0xbeefbeef, not 0xf00b412.
Instead use strcpy
char *t = malloc(3); //don't forget about the '\0'
strcpy(t, "as");
t = realloc(t, 6); //now the string has room to breathe
First off, don't do that:
char *t = malloc(2);
Do this instead:
char *t = malloc(2 * sizeof(char));
/* or this: */
char *t = calloc(2, sizeof(char));
It may not seem worth the effort, but otherwise you may run into problems later when you deal with types larger than 1 byte.
In this line:
t = "as";
You're assigning the address of the string literal "as", so your pointer no longer points to the memory you allocated. You need to copy the contents of the literal to your allocated memory:
char *t = calloc(3, sizeof(char));
/* "ar" is 3 char's: 'a', 'r' and the terminating 0 byte. */
strncpy(t, "ar", 3);
/* then later: */
t = realloc(t,sizeof(char)*6);
You can also just use strdup, which is safer:
#include <string.h>
char *t = strdup("ar");
t = realloc(t,sizeof(char)*6);
And don't forget to free the memory
free(t);
char *t = malloc(2);
this means you have created a pointer to a memory location that can hold 2 bytes
+-+-+
t -> | | |
+-+-+
when you do
t = "as";
now you made t point to somewhere else than what it originally was pointing to. now it no longer points to the heap
t = realloc(t,sizeof(char)*6);
now you are taking the pointer pointing to read only memory and try to realloc it.
when you use malloc you allocate space on the heap. t in this case is a pointer to that location, an address of where the block is.
in order to put something in that spot you need to copy the data there by dereferencing t, this is done by writing * in front of t:
*t = 'a'; // now 'a' is where t points
*(t+1)='s'; // now 's' is behind a, t still pointing to 'a'
however in C, a string is always terminated with a 0 (ASCII value) written as '\0' so in order to make it a string you need to append a \0
+-+-+--+
t -> |a|s|\0|
+-+-+--+
in order to do this you need to malloc 3 bytes instead, than you can add the \0 by writing *(t+2)='\0';
now t can be treated as pointing to a string and used in functions that takes strings as arguments e.g. strlen( t ) returns 2

Resources