Cannot change character in char array - c

According to this question: When should I use malloc in C and when don't I?
Using malloc to allocate memory should allow me to change one of the characters in the array. However, this program crashes at run time. Can someone please advise? (also free(ptr) causes a different crash which is why it is commented out).
char* ptr;
ptr = (char *)malloc(sizeof(char[10]));
ptr = "hello";
ptr[0] = 'H';
printf("The string contains: %s\n", ptr);
//free (ptr);
return 0;

Your program crashes because this line
ptr = "hello";
completely undoes the effect of malloc from the previous line:
ptr = malloc(sizeof(char[10])); // No need to cast to char*
and it also creates a memory leak along the way, because the address returned by malloc is irrecoverably lost after the assignment.
Once the assignment is done, an attempt to set ptr[0] = 'H' results in a crash, because you are trying to modify the memory of the string literal itself - i.e. undefined behavior.
In C strings need to be copied, not assigned if you want to modify them later. Replace the assignment with strcpy call to fix this problem.
strcpy(ptr, "hello");

There are several things that need to be fixed:
char* ptr = 0;
ptr = (char *)malloc(sizeof(char)*10);
if(!ptr)
return 0; // or something to indicate "memory allocation error"
strcpy(ptr, "hello");
ptr[0] = 'H';
printf("The string contains: %s\n", ptr);
free (ptr);
return 0;
This compiles and runs correctly in main()

Related

Segmentation fault in my strcpy

I'm writing my own strcpy due to the fact that the default one in string.h only accept a const char * as a source string to copy from.
I'm trying this very basic prototype (yes, the return isn't meaningful, I'm just trying things):
int copyStrings(char * dest, char * source){
int i=0;
while(source[i]!='\0'){
dest[i]=source[i];
i++;
}
dest[i]='\0';
return 0;
}
and it gives me SIGSEGV, Segmentation Fault error in gdb, at the line dest[i]=source[i], right at the first character. I'm pretty sure dest[i] isn't a string literal, so I should be able to modify it.
What am I doing wrong?
EDIT: here's the calling
int main(){
char * str = (char*)malloc((int)sizeof(double));
char * str2 = (char *)malloc((int)sizeof(int));
str = "hello";
str2 = "hey jude";
copyStrings(str2, str);
free(str);
free(str2);
return 0;
}
This is assigning a string literal to str2 - the very thing that you claim you aren't doing. This is actually the cause of your segfault.
str2 = "hey jude";
It also is causing a memory leak as prior to this, you malloc'd some memory and assigned it to str2 as well. But not enough memory to hold the string. Typically an int is 4 bytes and you need 9 bytes to store that string.
What you want to do is this, which allocates as many bytes as there are in the string, plus an extra one to store the \0 terminating character at the end.
str2 = malloc(strlen("hey jude")+1);
strcpy(str2,"hey jude");
or on some systems you can use POSIX function strdup() which effectively does the job of the above in one handy function call.
str2 = strdup("hey jude");
Let's go at it line by line and see where it goes wrong:
int main(){
char * str = (char*)malloc((int)sizeof(double));
char * str2 = (char *)malloc((int)sizeof(int));
str = "hello";
str2 = "hey jude";
copyStrings(str2, str);
free(str);
free(str2);
return 0;
}
int main(){ - this is an improper definition of main. Should be int main(int argc, char **argv)
char * str = (char*)malloc((int)sizeof(double)); - defines str, then allocates (probably) 8 bytes of memory and assigns its address to str. malloc takes a size_t argument, so the cast (int)sizeof(double) is incorrect. Also, in C the return value of malloc should never be cast. So this line should be char * str = malloc(sizeof(double));
char * str2 = (char *)malloc((int)sizeof(int)); - all the same problems as the preceding line. Should be char *str2 = malloc(sizeof(int));
str = "hello"; - causes a memory leak, because the memory you JUST ALLOCATED two lines earlier is now irretrievably lost. You've got two options here - either don't allocate the memory when defining str or free it first. Let's do the latter:
free(str);
str = "hello";
str2 = "hey jude"; - same problem, similar solution:
free(str2);
str2 = "hey jude";
copyStrings(str2, str); - here you're telling your routine to copy the constant string "hello" over the top of the constant string "hey jude". This will work fine on some systems, but will blow up on other systems. The question is in the treatment of the constant string "hey jude". If it's stored in modifiable memory the code will work just fine. If it's stored in memory which is marked as being unmodifiable, however, it will blow up. It seems that the latter is the case on your system. To fix this you probably want to go back to the previous line and change it to
str2 = malloc(20);
That's more memory than you'll need, but it will work just fine.
free(str); - you're attempting to free the constant string "hello", which is not dynamically allocated memory. This needed to be done prior to the assignment str = "hello";.
free(str2; - same problem as above. This needed to be done prior to the assignment str2 = "hey jude";.
} - correct
Best of luck.

Copy c-string char by char to dynamic char*

I have a const char* string, I want to copy that string character by character to dynamic `char*.
const char *constStr = "Hello world";
char *str = (char*) malloc(strlen(constStr)+1);
while(*constStr){
*str = *constStr;
constStr++;
str++;
}
printf("%s", str);
free(str);
The problem is that previous code just copies each character of constStr to only the first index of the str. I don't know why?
As others have pointed out, you are incrementing str pointer in each iteration, so you always end up printing the end of the string.
You can instead iterate over each character without incrementing the pointer. The following code worked for me:
const char *constStr = "Hello world";
int len = strlen(constStr);
char *str = (char *) malloc(len + 1);
int i;
for (i = 0; i <= len; ++i) {
str[i] = constStr[i];
}
printf("%s", str);
free(str);
Yes you didn't null terminate the string. That was the primary problem. To be more clear, it is not that you didn't nul terminate the string which is the problem but rather your use of them where a pointer to a nul terminated char array is expected is the problem. But even if you did there was significant amount of problems in the code.
You allocated the memory and the casted the return value of malloc which is unnecessary. void* to char* conversion is implicitly done.
malloc might not be able to service the request, it might return a null pointer. It is important to
check for this to prevent later attempts to dereference the null pointer.
Then you started copying - you copied everything except the NUL terminating character. And then you passed it to printf's %s format specifier which expects a pointer to a null terminated char array. This is undefined behavior.
The one position, in the str is uninitialized - beware that accessing uninitialized value may lead to undefined behavior.
Also there is another problem, From standard ยง7.22.3.3
The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.
Yes so is is the case here? No. when you called free(str) str is not pointing to the dynamically allocated memory returned by the malloc. This is again undefined behavior.
The solution always is to keep a pointer which stores the address of the allocated chunk. The other answers already showed them (without repeating them - both of them provides a good solution).
You can use strdup or strcpy also - even if you don't need them now - get accustomed with them. It helps to know those. And yes strdup is not part of standard, it is a POSIX standard thing.
Example:
const char *constStr = "Hello world";
char *str = malloc(strlen(constStr)+1);
if( !str ){
perror("malloc");
exit(EXIT_FAILURE);
}
char *sstr = str;
while(*constStr){
*str = *constStr;
constStr++;
str++;
}
*str = 0;
printf("%s", sstr);
free(sstr);
Here's the "classical" string copy solution:
const char *constStr = "Hello world";
char *str = malloc(strlen(constStr) + 1), *p = str;
/* Do not forget to check if str!=NULL !*/
while((*p++ = *constStr++));
puts(str);
The problem is that previous code just copies each character of
constStr to only the first index of the str. I don't know why?
Use index variable.
Don't forget terminating '\0' because you have a good chance of segmentation fault.

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.

Why cannot be pointer free() after pointing to string literal

There are some related discussions about my problem but there are no clearly explanations about my problem.
I thought that I must free() whatever I malloc(), no matter when or where but I have to do it, to prevent a memory leak.
So i have the following program:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int *ptr;
ptr = malloc(256);
if (ptr == NULL) {
printf("Out of memory\n");
return 1;
}
*ptr = 10;
printf("The value of PTR is:\t%d\n",*ptr);
free(ptr);
return 0;
}
I have a pointer and I dynamically allocated some memory (256), then I checked for NULL letter I free() it.
Until here everything is OK: to the pointer was dynamically allocated some memory and then I free() it.
Now i will use a char pointer this time and after i will dynamically allocated some memory (256), i will point that pointer to a string literal, lets say MICHI:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
char *ptr;
ptr = malloc(256);
if (ptr == NULL) {
printf("Out of memory\n");
return 1;
}
ptr = "michi";
printf("%s",ptr);
free(ptr);
return 0;
}
Here I am doing something wrong because if i try to free() it, well it will not work because it happens that i'm going to free a non-heap object.
So i'm lost in here, because i thought that everything you malloc() you have to free() it.
What exactly make that pointer, after points to a string literal, to not need to be free()ed
ptr = malloc(256);
...
ptr = "michi";
printf("%s",ptr);
free(ptr);
As you allocate memory to ptr and then you make it point to string literal. Thus pointer ptr no longer points to memory allocated by malloc.
And to free memory not allocated by malloc or similar functions cause error in program.
Do this instead:
strcpy(ptr,"michi");
In the first program you allocated memory
ptr = malloc(256);
and initialized its first sizeof( int ) bytes with integer value 10.
*ptr = 10;
The pointer itself was not changed. So in this statement
free(ptr);
pointer ptr points to the memory that was allocated using malloc.
In the second program you allocated memory the same way as in the first program
ptr = malloc(256);
But then you reassigned the pointer itself with the address of the first character of string literal "michi"
ptr = "michi";
Compare the left sides of this assignment
*ptr = 10;
and of this assignment
ptr = "michi";
As you see they are different. In the first case you are changing the allocated memory while in the second case you are changing the pointer itself.
Thus in this statement
free(ptr);
pointer ptr does not point to the memory that was previously allocated. It points to the memory occupied by the string literal that was not allocated using malloc.
Thus this statement is wrong and the program has a memory leak because the previous memory that was allocated using malloc was not freed,
Because constant literals are stored in a way for the lifetime of the program, in a read-only region of memory in most of the platforms.
When you use free you are trying to free the memory allocated, not the pointer itself, that's why it's not gonna work if you try to do that in a read-only region of memory
When you reassign your pointer you're losing track of the allocated memory and therefore creating a memory leak.
The memory leak is created because you first allocated the memory and assign it to your pointer, when you've a pointer pointing to it you can easily free that memory, but when you don't have any more reference to that memory you can't.
That's what's happening, when assign the literal to the pointer there's no more reference to that address, it was allocated but it's not reachable anymore, in this way you can't free the memory.
The problem is that you have lost the pointer the second you assigned another value to it:
ptr = malloc(256);
if (ptr == NULL) {
printf("Out of memory\n");
return 1;
}
// here you should free your memory
ptr = "michi";
printf("%s",ptr);
// this fails, because ptr now points to the const static string "michi" you have coded yourself. The assignment didn't copy it, just changed what ptr points to.
free(ptr);
Try this.
#include <stdio.h>
int main(void)
{
char *str:
str = (char*)malloc(sizeof(str) * 4);
printf("Addr of str before: %p\n", str);
str = "Joe";
printf("Addr of str after: %p\n",str);
return(0);
}
/* you will get the following addresses:
Addr of str before: 0x51fc040
Addr of str after: 0x4006f0
this is becuase you changed where str points to. 0x51fc040 is memory allocated using malloc and 0x4006f0 is the memory Adress of the string literal "Joe".
I would advice the following...*/
#include <stdio.h>
int main(void)
{
char *str;
str = (char*)malloc(sizeof(str) * 4);
printf("Addr of str before: %p\n", str);
str =strncpy(str, "Joe", 4);
printf("Addr of str after: %p\n",str);
free(str);
return (0);
}
/* you will get the following addresses:
Addr of str before: 0x51fc040
Addr of str after: 0x51fc040
This is because strncpy copies the string literal to the memory dynamically allocated. and it is safer than stcpy, since it prevents buffer overflow

munmap_chunk(): invalid pointer

I've spotted the error in my program and decided to write a simple one, which would help me understand what's going on. Here it is :
#include <stdio.h>
#include <stdlib.h>
char * first()
{
char * word = malloc(sizeof(char) * 10);
word[0] = 'a';
word[1] = 'b';
word[2] = '\0';
return word;
}
char * second ()
{
char * word = malloc(sizeof(char) * 10);
word = "ab";
return word;
}
int main ()
{
char * out = first();
printf("%s", out);
free(out);
out = second();
printf("%s", out);
free(out);
return 0;
}
The first() function is working properly, but the second() (exactly the free(out) ) genarates error:
Error in `./a.out': munmap_chunk(): invalid pointer: 0x0000000000400714 ***
ababAborted (core dumped)
I don't understand why the first function is correct, but the second isn't. Could anyone explain why?
In the function second(), the assignment word = "ab"; assigns a new pointer to word, overwriting the pointer obtained through malloc(). When you call free() on the pointer later on, the program crashes because you pass a pointer to free() that has not been obtained through malloc().
Assigning string literals does not have the effect of copying their content as you might have thought. To copy the content of a string literal, use strcpy():
strcpy(word, "ab");
In function char * second
char * word = malloc(sizeof(char) * 10);
word = "ab";
The second statement word = "ab"; changes word to point away from the allocated memory.You are not copying the string "ab" to the area of heap allocated by malloc.
And to free a memory that is not allocated by malloc or similar functions crashes your program.
Attempting to free an invalid pointer (a pointer to a memory block that was not allocated by calloc, malloc, or realloc) may affect subsequent allocation requests and cause errors.
You should use here strcpy as also suggested by others.

Resources