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
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 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.
I am trying to copy a string into another char pointer variable using strcpy function.But I always get segmentation fault.Here is my code.
/* strcat example */
#include <stdio.h>
#include <string.h>
int main()
{
char str[100]="";
char *pch3;
strcpy(pch3,"Ravi");
//strcat(str,pch3); //Segmnetation fault.
puts(pch3);
return 0;
}
If I do the same thing in this one I still get segmentation fault.
else
{
misc_rec_cnt++;
fp1=fopen("breast-cancer-wisconsin-miscellaneous.data","a");
fprintf(fp1,"%s",line2);
fclose(fp1);
fp2=fopen("missingSCNs.data","a");
pch2=strtok(line2,",");
fprintf(fp2,"%s\n",pch2);
fclose(fp2);
//pch3=(char *)malloc(sizeof(char)*strlen(line3));
pch3 = strtok(line3,",");
while(pch3!=NULL)
{
if(strcmp(pch3,"?") == 0)
{
strcat(str1,"0");
strcat(str1,",");
}
else
{
//strcat(str1,pch3);
strcat(str1,",");
}
pch3 = strtok(NULL,",");
}
strlen1=strlen(str1);
memcpy(str2,str1,strlen1-1);
fp3=fopen("breast-cancer-wisconsin-miscellaneous-cleansed.data","a");
fprintf(fp3,"%s\n",str2);
fclose(fp3);
}
You need to allocate the space for pch3 before you copy to it. Use malloc to create a char array large enough to accomodate the elements of your source string before you copy it. What you are currently doing is declaring a char pointer and not initialising it. Therefore the memory location that it points to could be anywhere - and that means that you should probably not be attempting to write to it - which is why you are getting the segfault. Using malloc will allow you to allocate a region of memory that you are safe to write to and this will solve your problem (assuming the call to malloc succeeds). You cannot just go writing data to random memory locations without getting segfaults and access violations.
pch3 is a char pointer, but it doesn't have any storage associated with it which is the cause of the problem. Call malloc() to allocate some memory that the pch3 pointer can point to and you should be ok.
At this point you have a char pointer that is uninitialized and just pointing somewhere unknown. So try this:
pch3 = (char *)malloc(sizeof(char) * 100); /* 100 just as an example */
This tutorial might be helpful or this SO question: Allocating char array using malloc
pch3 is an unallocated pointer, so you're writing data to a location that doesn't exist. Did you mean to assign it to str?
char str[100]="";
char *pch3;
pch3 = str;
strcpy(pch3,"Ravi");
I'd recommend that you first allocate memory before copying data to a random place.
strcpy(pch3=(char*)malloc(sizeof("Ravi")),"Ravi");
but better check if it didn't return null pointer.
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