I don't understand why, in this code, the call to "free" cause a segmentation fault:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *char_arr_allocator(int length);
int main(int argc, char* argv[0]){
char* stringa = NULL;
stringa = char_arr_allocator(100);
printf("stringa address: %p\n", stringa); // same address as "arr"
printf("stringa: %s\n",stringa);
//free(stringa);
return 0;
}
char *char_arr_allocator(int length) {
char *arr;
arr = malloc(length*sizeof(char));
arr = "xxxxxxx";
printf("arr address: %p\n", arr); // same address as "stringa"
return arr;
}
Can someone explain it to me?
Thanks,
Segolas
You are allocating the memory using malloc correctly:
arr = malloc(length*sizeof(char));
then you do this:
arr = "xxxxxxx";
this will cause arr point to the address of the string literal "xxxxxxx", leaking your malloced memory. And also calling free on address of string literal leads to undefined behavior.
If you want to copy the string into the allocated memory use strcpy as:
strcpy(arr,"xxxxxxx");
The third line of char_arr_allocator() wipes out your malloc() result and replaces it with a chunk of static memory in the data page. Calling free() on this blows up.
Use str[n]cpy() to copy the string literal to the buffer instead.
When you write a constant string in C, such as "xxxxxx", what happens is that that string goes directly into the executable. When you refer to it in your source, it gets replaced with a pointer to that memory. So you can read the line
arr = "xxxxxxx";
Treating arr as a number as something like:
arr = 12345678;
Where that number is an address. malloc has returned a different address, and you threw that away when you assigned a new address to arr. You are getting a segfault because you are trying to free a constant string which is directly in your executable -- you never allocated it.
You are setting arr to the return value of malloc(), which is correct. But you are then reassigning it to point at the string constant "xxxxxxx". So when you call free(), you're asking the runtime to free a string constant, which causes the seg fault.
Related
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 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.
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
I don't understand why, in this code, the call to "free" cause a segmentation fault:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *char_arr_allocator(int length);
int main(int argc, char* argv[0]){
char* stringa = NULL;
stringa = char_arr_allocator(100);
printf("stringa address: %p\n", stringa); // same address as "arr"
printf("stringa: %s\n",stringa);
//free(stringa);
return 0;
}
char *char_arr_allocator(int length) {
char *arr;
arr = malloc(length*sizeof(char));
arr = "xxxxxxx";
printf("arr address: %p\n", arr); // same address as "stringa"
return arr;
}
Can someone explain it to me?
Thanks,
Segolas
You are allocating the memory using malloc correctly:
arr = malloc(length*sizeof(char));
then you do this:
arr = "xxxxxxx";
this will cause arr point to the address of the string literal "xxxxxxx", leaking your malloced memory. And also calling free on address of string literal leads to undefined behavior.
If you want to copy the string into the allocated memory use strcpy as:
strcpy(arr,"xxxxxxx");
The third line of char_arr_allocator() wipes out your malloc() result and replaces it with a chunk of static memory in the data page. Calling free() on this blows up.
Use str[n]cpy() to copy the string literal to the buffer instead.
When you write a constant string in C, such as "xxxxxx", what happens is that that string goes directly into the executable. When you refer to it in your source, it gets replaced with a pointer to that memory. So you can read the line
arr = "xxxxxxx";
Treating arr as a number as something like:
arr = 12345678;
Where that number is an address. malloc has returned a different address, and you threw that away when you assigned a new address to arr. You are getting a segfault because you are trying to free a constant string which is directly in your executable -- you never allocated it.
You are setting arr to the return value of malloc(), which is correct. But you are then reassigning it to point at the string constant "xxxxxxx". So when you call free(), you're asking the runtime to free a string constant, which causes the seg fault.