Strcpy Segmentation Fault C - c

I am learning some new things and get stuck on a simple strcpy operation.
I don't understand why first time when I print works but second time it doesn't.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char *name;
char *altname;
name=(char *)malloc(60*sizeof(char));
name="Hello World!";
altname=name;
printf("%s \n", altname);
altname=NULL;
strcpy(altname,name);
printf("%s \n", altname);
return 1;
}

The problems start here:
name=(char *)malloc(60*sizeof(char));
name="Hello World!";
You replaced the value returned by malloc with a string literal.
You leaked memory (since you can't regain the pointer value returned by malloc). All calls to malloc are matched with a corresponding call to free. Since that pointer value is gone, the opportunity to call free with that pointer value is also gone.
You further on write to a NULL pointer, which is undefined behavior (which in your case, produced a segmentation fault).

You need to allocate memory for altname :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char *name;
char *altname;
name=(char *)malloc(60*sizeof(char));
name="Hello World!";
altname=name;
printf("%s \n", altname);
altname=NULL;
// allocate memory, so strcpy has space to write on ;)
altname=(char *)malloc(60*sizeof(char));
strcpy(altname,name);
printf("%s \n", altname);
return 1;
}

The first time, you are making altname point to the same place as name. This is OK, because name points to a valid char* (the first element ofthe "Hello World!" literal)
// both point to beginning of "Hello World!" literal
altname=name;
The second time, you attempt to copy the data pointed at by name into the place pointed at by altname, which at this stage points to NULL. So you attempt to write to NULL, which is the source of the error.
strncpy requires that the destination buffer be writable, and large enough to copy the source string's data into. You need to make altname point to a buffer that is large enough for the contents of the string name points to.
altname = (char*)malloc(60*strlen(name)+1); // +1 for nul terminator
strcpy(altname, name);
Also note that when you set name = "Hello World!", you leak the memory it originally pointed to. You need to free that first:
free(name);
name = "Hello World!";

You are trying to assign value to altname which has no space to store. First allocate memory to altname then assign
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char *name;
char *altname;
name=(char *)malloc(60*sizeof(char));
name="Hello World!";
altname=name;
printf("%s \n", altname);
altname=NULL;
altname=(char *)malloc(sizeof(name)); // allocate memory
strcpy(altname,name); // Now assign
printf("%s \n", altname);
return 1;
}

Related

Memory fault and pointer to string

So I'm trying to reverse a string, but I get a memory fault. Memory for s and s1 is initialized enough to accomodate the '/0' character as well.
Interestingly if I remove *s=*s1 and print s1 instead the program works.
But I haven't even set the "\0" character at the end of s1 so how does it even know where to stop printing?
And in the case below what exactly is the issue?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main(void)
{
char *s = "abcdefghijklmnop", *s1=malloc(17);
int i;
for(i=0;i<strlen(s);i++)
{
*(s1+i) = *(s+strlen(s)-1-i);
}
*s=*s1;
printf("%s",s);
}
The char *s = "abcdefghijklmnop" is a string literal which is often in read-only memory.
An error will be generated if you attempt to modify a string literal.
You attempt to replace the first character in s with the first character in s1 when you do *s=*s+1.
If s wasn't a string literal, you should've done s=s1 instead of *s=*s1 to make s its reverse.
More about this:
https://softwareengineering.stackexchange.com/questions/294748/why-are-c-string-literals-read-only
String literals: Where do they go?
where in memory are string literals ? stack / heap?
The correct string is printed with printf("%s", s1); even if no \0 was stored because the memory next to the last character just happened to be 0 which is equivalent to \0. This needn't always be so and cannot be relied upon as malloc() doesn't initialise the memory that it allocates.
But calloc() will initialise the memory it allocates to 0.
See more here.
In your code *s=*s1 only copy the first content of s1 into s. i.e, *(s+0)=*(s1+0) not the entire string. So we need to assign the address of s1 to s. i.e, s=s1.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char *s = "abcdefghijklmnop", *s1=malloc(17);
int i;
for(i=0;i<strlen(s);i++)
{
*(s1+i) = *(s+strlen(s)-1-i);
}
s=s1;
printf("%s",s);
free(s1);
return 0;
}
It is good practice to free the memory after its use.

Change string value by address C

I'm trying to change the value of a string by passing its address to a function.
I get NULL as a result.I tried strcpy but it dosen't work for pointers on strings.
Code :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void changeStr (char ** tmpP){
char* test="Hello world !";
char** add=&test;
tmpP=add;
}
int main() {
char* tmp;
changeStr(&tmp);
printf("\n %s \n",tmp);
return 0;
}
result :
(NULL)
Currently the behaviour of your code is undefined as changeStr is a no-op, and you are attempting to call printf with the uninitialised variable tmp. That accounts for your (arbitrary) output. On other occasions the compiler might eat your cat.
add has automatic storage duration, and tmpP is the result of a value copy of &tmp from the caller. These assignments, although perfectly valid, are not visible to the calling function main().
The solution is to write
*tmpP = "Hello World";
as the only statement in changeStr.
You should note that tmp in main() will point to a read-only string literal.
What your doing is the mistake, tmpP=add; you thought that the add value will point to tmpP.
If you want to change the value of string passed to function, you can do in this way. I saw already #Bathseba pointed out.
Try this,
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void changeStr (char ** tmpP){
char* test;
char** add=&test;
*tmpP= "Hello world !";
}
int main() {
/* Here it has string cruel that pass to function*/
char* tmp="Cruel";
changeStr(&tmp);
printf("\n %s \n",tmp);
return 0;
}
Output:
Hello world !
What you did.
void changeStr (char ** tmpP){
char* test = "Hello world !";
char** add=&test;
tmpP=add; //<-- Here your assigning add to tmpP, it shouldn't.
}

Can a string pointer in C be directly assigned a string literal?

The following program works fine, and I'm surprised why :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void xyz(char **value)
{
// *value = strdup("abc");
*value = "abc"; // <-- ??????????
}
int main(void)
{
char *s1;
xyz(&s1);
printf("s1 : %s \n", s1);
}
Output :
s1 : abc
My understanding was that I have to use strdup() function to allocate memory for a string in C for which I have not allocated memory. But in this case the program seems to be working fine by just assigning string value using " ", can anyone please explain ?
String literals don't exist in the ether. They reside in your programs memory and have an address.
Consequently you can assign that address to pointers. The behavior of your program is well defined, and nothing bad will happen, so long as you don't attempt to modify a literal through a pointer.
For that reason, it's best to make the compiler work for you by being const correct. Prefer to mark the pointee type as const whenever possible, and your compiler will object to modification attempts.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void xyz(char const **value)
{
*value = "abc";
}
int main(void)
{
char const *s1;
xyz(&s1);
printf("s1 : %s \n", s1);
s1[0] = 'a'; << Error on this line
}
Your program works fine because string literal "abc" are character arrays , and what actually happens while assigning a string literal to a pointer is , the compiler first creates a character array and then return the address of the first element of the array just like when we call the name of any other array.
so in your program you have passed address of a char pointer to the function xyz
and
*value = "abc";
for this statement , compiler first creates a character array in the memory and then returns its address which in turn gets stored in the char pointer.It is worth knowing that the compiler creates the char array in read only memory.Thus , the address returned refers to a const char array.Any attempt to modify its value will return it compile-time error.
You can define a string in C with char *str = "some string";, str is a pointer which points to the location of the first letter in a string.

What is the meaning of Bus: error 10 in C

Below is my code
#import <stdio.h>
#import <string.h>
int main(int argc, const char *argv[])
{
char *str = "First string";
char *str2 = "Second string";
strcpy(str, str2);
return 0;
}
It compiles just fine without any warning or errors, but when I run the code I get the error below
Bus error: 10
What did I miss ?
For one, you can't modify string literals. It's undefined behavior.
To fix that you can make str a local array:
char str[] = "First string";
Now, you will have a second problem, is that str isn't large enough to hold str2. So you will need to increase the length of it. Otherwise, you will overrun str - which is also undefined behavior.
To get around this second problem, you either need to make str at least as long as str2. Or allocate it dynamically:
char *str2 = "Second string";
char *str = malloc(strlen(str2) + 1); // Allocate memory
// Maybe check for NULL.
strcpy(str, str2);
// Always remember to free it.
free(str);
There are other more elegant ways to do this involving VLAs (in C99) and stack allocation, but I won't go into those as their use is somewhat questionable.
As #SangeethSaravanaraj pointed out in the comments, everyone missed the #import. It should be #include:
#include <stdio.h>
#include <string.h>
There is no space allocated for the strings. use array (or) pointers with malloc() and free()
Other than that
#import <stdio.h>
#import <string.h>
should be
#include <stdio.h>
#include <string.h>
NOTE:
anything that is malloc()ed must be free()'ed
you need to allocate n + 1 bytes for a string which is of length n (the last byte is for \0)
Please you the following code as a reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
//char *str1 = "First string";
char *str1 = "First string is a big string";
char *str2 = NULL;
if ((str2 = (char *) malloc(sizeof(char) * strlen(str1) + 1)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
strcpy(str2, str1);
printf("str1 : %s \n", str1);
printf("str2 : %s \n", str2);
free(str2);
return 0;
}
str2 is pointing to a statically allocated constant character array. You can't write to it/over it. You need to dynamically allocate space via the *alloc family of functions.
string literals are non-modifiable in C
Your code attempts to overwrite a string literal. This is undefined behaviour.
There are several ways to fix this:
use malloc() then strcpy() then free();
turn str into an array and use strcpy();
use strdup().
this is because str is pointing to a string literal means a constant string ...but you are trying to modify it by copying .
Note : if it would have been an error due to memory allocation it would have been given segmentation fault at the run time .But this error is coming due to constant string modification or you can go through the below for more details abt bus error :
Bus errors are rare nowadays on x86 and occur when your processor cannot even attempt the memory access requested, typically:
using a processor instruction with an address that does not satisfy
its alignment requirements.
Segmentation faults occur when accessing memory which does not belong to your process, they are very common and are typically the result of:
using a pointer to something that was deallocated.
using an uninitialized hence bogus pointer.
using a null pointer.
overflowing a buffer.
To be more precise this is not manipulating the pointer itself that will cause issues, it's accessing the memory it points to (dereferencing).
Let me explain why you do you got this error "Bus error: 10"
char *str1 = "First string";
// for this statement the memory will be allocated into the CODE/TEXT segment which is READ-ONLY
char *str2 = "Second string";
// for this statement the memory will be allocated into the CODE/TEXT segment which is READ-ONLY
strcpy(str1, str2);
// This function will copy the content from str2 into str1, this is not possible because you are try to perform READ WRITE operation inside the READ-ONLY segment.Which was the root cause
If you want to perform string manipulation use automatic variables(STACK segment) or dynamic variables(HEAP segment)
Vasanth
Whenever you are using pointer variables ( the asterix ) such as
char *str = "First string";
you need to asign memory to it
str = malloc(strlen(*str))
None of the mentioned solution, worked for me as I couldn't find where the error was coming from. So, I simply deleted my node_modules and re-installed it. And the error disappeared; my code started working again

simple string runtime error in C?

This code compiles fine but give segmentation fault error while running? Can anyone tell why?
#include <stdio.h>
#include <string.h>
#include <math.h>
int main() {
const char s2[] = "asdfasdf";
char* s1;
strcpy(s1, s2);
printf("%s", s1);
return 0;
}
You allocated space for a single pointer, s1, but not the bytes pointed at by s1.
A solution is to dynamically allocate memory for s1:
s1 = (char *)malloc(strlen(s2) + 1);
strcpy(s1, s2);
Keep in mind that you need to allocate one more byte of memory (the +1 in the call to malloc) than the number of characters in s2 because there is an implicit NULL byte at the end.
See C Memory Management (Stack Overflow) for more information.
You didn't allocate memory for s1. You have a pointer to s1 but no memory allocated for the strcpy to copy the value of s2 into.
char *s1 = malloc( strlen(s2) + 1 );
strcpy( s1, s2 );
You have not allocated any memory to s1. It is a pointer to nothing.
char* s1 = malloc(sizeof(s2));
strcpy(s1, s2);
printf("%s", s1);
free(s1);
The problem is that s1 does not have any memory associated with it. strcpy does not call malloc().
You could either do:
char s1[10];
or
char *s1 = malloc(10);
What they all said, you need to allocate the space for s1. What everyone else has posted will work just fine, however, if you want a simpler way to allocate space for an existing string and copy it into a new pointer then use strdup like this:
#include <stdio.h>
#include <string.h>
#include <math.h>
using namespace std;
int main() {
const char s2[] = "asdfasdf";
char* s1;
s1 = strdup(s2);
printf("%s", s1);
return 0;
}
Someone mentioned strdup earlier, that would be a way to use it. Most systems should support it since it is in the standard C libaries. But apparently some don't. So if it returns an error either write your own using the method already mentioned, or just use the method already mentioned ;)
No one yet has pointed out the potential of strdup (String Duplicate) to address this problem.
#include <stdio.h>
#include <string.h>
#include <math.h>
using namespace std;
int main() {
const char s2[] = "asdfasdf";
char* s1;
s1 = strdup(s2); // Allocates memory, must be freed later.
printf("%s", s1);
free(s1); // Allocated in strdup, 2 lines above
return 0;
}
You need to allocate the destination (and using namespace std; isn't C but C++, the rest of the code is C).
You have to allocate memory to the pointer s1. If you don't do that, it will be pointing somewhere unknown, and thus arriving at the segmentation fault. The correct code should be:
#include <stdio.h>
#include <string.h>
#include <math.h>
int main() {
const char s2[] = "asdfasdf";
char* s1 = malloc(21 * sizeof(s2[0]));
strcpy(s1,s2);
printf("%s",s1);
return 0;
}

Resources