why does it this c program give segmentation fault [duplicate] - c

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 10 months ago.
#include <stdio.h>
#include <stdlib.h>
int main() {
char *str="hello";
str[0]='H';
return 0;
}
If I use an array I can do use subscript to assign the first character. What's different about using a char pointer here that causes a segmentation fault?

In this code snippet
char *str="hello";
str[0]='H';
you are trying to change a string literal pointed to by the pointer str. Any attempt to change a string literal results in undefined behavior.
From the C Standard (6.4.5 String literals)
7 It is unspecified whether these arrays are distinct provided their
elements have the appropriate values. If the program attempts to
modify such an array, the behavior is undefined.
So though in C opposite to C++ string literals have types of non-constant arrays it is always better to declare pointers to string literals with the qualifier const.
const char *str="hello";
You could declare a character array initialized by the string literal and change the array itself like
char str[] ="hello";
str[0]='H';

okay, I got the answer from this wiki - https://en.wikipedia.org/wiki/Segmentation_fault#Writing_to_read-only_memory
The char pointer declared like that writes to a read-only segment of the process, editing that gives a segmentation fault (specifically SEGV_ACCERR which is defined as invalid permissions for mapped object (see here)
An array on the other hand similarly allocated will be done so on the stack and so can be edited.

Related

Why does scanf("%s") behave strangely with char*? [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 2 years ago.
I was trying to solve this problem
When i create a char * and pass it into scanf:
char* input = "";
scanf("%s", input);
It behaves weirdly.
However, when i change the definition and initalize 1000 chars to \0:
char input[1000] = { '\0' };
It behaves properly. Why is it that way?
I'm guessing you're seeing a segmentation fault. When you declare char* input = "";, you're causing input to be a pointer directed at a string literal. String literals are stored in a read-only section of memory. Therefore, trying to overwrite the data with scanf is an invalid use of memory.
However, when you declare char input[1000];, you've now got an array on the stack, which is a section of memory which can be written to. That's why that code works.
First question is what does this declare?
char* input = "";
That's a single byte in a non-mutable (read-only) area of memory. If you write anything to it, that's undefined behaviour, or something more colloquially described as weird behaviour.
When you re-write it correctly you get a 1000 character buffer and you can read to it without undefined behaviour, provided your input is < 1000 characters.

I can't seem to know how to concatenate two char pointer strings using strcat, is it not correct? [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 3 years ago.
I can't concatenate two pointer strings using strcat, is it not possible?
I tried using them like strcat(s1,s2), and strcat(*s1,*s2), and all and it still doesn't work.
char *s1="Hello";
char *s2="Bye";
printf("%s\n",s1);
strcat(s1,s2);
printf("%s",s1);
When I run it prints the first "Hello" that is before the strcat, but the code doesn't display the remaining output and doesn't return 0.
Your approach cannot work, for several reasons:
char *s1="Hello";
s1 points to a read-only string (literal). You cannnot modify it.
strcat(s1,s2);
This cannot work because there is not enough room in s1 to add s2.
Use:
char s1[30]="Hello";
char *s2="Bye";
strcat(s1,s2);
With char s1[30]="Hello"; the compiler allocates an array for 30 charactes and then copies the string "Hello" into that array. Unused elements are set to zero.
With char *s2="Bye"; the compiler makes s2 point to a read-only string, so to make that explicit it is better to write const char *s2="Bye";

Segmentation Fault in char pointer [duplicate]

This question already has answers here:
Modify a string with pointer [duplicate]
(4 answers)
Closed 5 years ago.
I am getting segmentation fault when running the below code. What could be the reason for this error? Please help
int main()
{
char *str2 = "Hello";
str2[3] = 'J';
printf("%s\n",str2);
return 0;
}
It is a undefined behaviour because you are trying to modify the content of a string literal. A string literal mainly stored in a read only location. so you do not modify it, otherwise it is invoked undefined behaviour.
C11 ยง6.4.5 String literals(Paragraph 7):
It is unspecified whether these arrays are distinct provided their
elements have the appropriate values.If the program attempts to
modify a string literal of either form, the behavior is undefined"
You aren't allowed to modify a string constant, and in this case it's causing a runtime error. You can fix it by changing the declaration of str2 to:
char str2[] = "Hello";
This makes it an array, rather than a pointer to a string constant.
You are not allowed to modify the memory pointed to by char* variables initialized with string literals. It is read-only.

C error about pointer [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 6 years ago.
Can anyone explain why this code not work, pls!! Thanks you so much!
#include <stdio.h>
void changer(char * tp)
{
int i=0;
tp[0]='b';
}
int main(void)
{
char *st="aaab";
changer(st);
printf("%s",st);
}
This statement
tp[0]='b';
results in undefined behaviour because tp points to a string literal. You are not allowed to modify a string literal in C.
Instead you could use an array:
char st[] = "aaab";
which you'd be able to modify.
char *st="aaab";
This statement indicates that st is a pointer variable but "aaab" is string constant.
Instead try
char st[]="aaab";
This statement indicates that it declares st as array [5] of char and copies the contents of the string literal. Here st is a constant pointer.

Compiler crashes when printing a pointer related code [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 7 years ago.
Today when learning pointer in C, I have faced a problem. I wrote this code:
#include<stdio.h>
int main()
{
char *p="XAD";
printf("%c\n",(*p));
printf("%c\n",++(*p));
return 0;
}
First printf() shows correct output and it is X. But for second output, compiler crashes. But why? If (*p) gives 'X'(as expected), then ++(*p) should give 'Y'. Shouldn't it?
Here:
char *p="XAD";
You create a pointer p and assign it to the string literal "XAD". String literals are immutable, meaning that it cannot be changed. The ++(*p) dereferences the pointer p and increments it, thus attempting to change the contents of the string literal (Specifically, the first character). Attempting to modify a string literal leads to Undefined Behavior as seen in the C11 standard (emphasis mine):
6.4.5 String literals
[...]
It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined
Fix the problem by either declaring p as an array or using (*p)+1 instead of ++(*p). Using the former will not modify the contents of the string literal while the latter does.
The pointer p points to a string literal. Modifying a string literal results in undefined behaviour in C.
Change
char *p="XAD";
to
char p[]="XAD";
which will allow you to modify it since p is an array here.
While char *p="abc"; is perfectly valid in C, in general, string literals should be declared with const keyword as you are not allowed to modify it anyway. This will help catch an accidental change. It should have been of type const char[] but it is of type char [] is because of "historical" reasons (C++ corrected it).
Or you simply interested in printing a modified value, you can do:
printf("%c\n", (*p) + 1);
as suggested by #alk, which does what you code attempts to do but without modifying the string itself.

Resources