Why does this code produce a segmentation fault? [duplicate] - c

This question already has answers here:
Access violation error when reversing a string c++ [duplicate]
(1 answer)
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 9 years ago.
On line 18, I get a seg fault in the first iteration (i = 0).
#include <stdio.h>
int main(void) {
char* str = "mono";
int length = 0;
int i;
for (i = 0; ; i++) {
if (str[i] == '\0') {
break;
} else {
length++;
}
}
for (i = 0; i < length / 2; i++) {
char temp = str[length - i - 1];
str[length - i - 1] = str[i]; // line 18
str[i] = temp;
}
printf("%s", str);
return 0;
}
I wrote this algorithm to reverse a string.

You are modifying a string literal:
char* str = "mono";
and string literals are non-modifiable in C.
To fix your issue, use an an array initialized by the string literal:
char str[] = "mono";

Runtime Error:
char* str = "mono"; // str points to an address in the code-section, which is a Read-Only section
str[1] = 'x'; // Illegal memory access violation
Compilation Error:
const char* str = "mono"; // This is a correct declaration, which will prevent the runtime error above
str[1] = 'x'; // The compiler will not allow this
All Good:
char str[] = "mono"; // str points to an address in the stack or the data-section, which are both Read-Write sections
str[1] = 'x'; // Works OK
Notes:
In all cases, a string "mono" is placed in the code-section of the program.
In the last example, the contents of that string are copied into the str array.
In the last example, the str array is located in the stack if str is a non-static local variable, and in the data-section of the program otherwise.

Related

Bus error when dereferencing the same address [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 months ago.
I'm trying the squeeze program from K&R. However, I keep getting a bus error. The code below directly triggers the problem. Shouldn't this be portable?
int main() {
char* str = "foo";
for (int i = 0, j = 0; str[i]; ++i)
str[j] = '.';
}
The function from the book:
void squeeze(char s[], int c)
{
int i, j;
for (i = j = 0; s[i] != '\0'; i++)
if (s[i] != c)
s[j++] = s[i];
s[j] = '\0';
}
str points to a string constant. Such constants are read only, so attempting to modify them triggers undefined behavior which in your particular case manifests in the program crashing.
Instead, declare str as an array, which can be modified:
char str[] = "foo";

Reversing a string stored using a pointer in C gives error [duplicate]

This question already has answers here:
Why does this C program throw a segmentation fault at runtime?
(3 answers)
using pointer to char vs char array [duplicate]
(1 answer)
Closed 7 months ago.
I was trying to reverse a string stored in a pointer but I keep receiving the error
EXC_BAD_ACCESS (code=2, address=0x100003f7c)
when code enters the for loop.
It works if I change char *s to char s[ ] .
#include <stdio.h>
#include <string.h>
int main(void)
{
char *s = "hello";
char c;
int i,j;
for (i = 0, j = strlen(s)-1; i < j; i++, j--)
{
c = s[i], s[i] = s[j], s[j] = c;
}
printf("%s",s);
}
Code editor - Visual Studio Code
OS - macOS

Change char by index [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 last year.
Trying to change char by index:
char *p = "test";
for (int i = 0; i < 4; ++i) {
p[i] = 50;
}
printf("%s\n", p);//test
What I'm doing wrong?
you cannot change a literal,
char*p="test";
doesnt copy the literal. You should do
char p[] = "test";
or
#include <string.h>
....
char *p = strdup("test");
if you want to deal with a pointer rather than a char array.
The line
char *p = "test";
will make the pointer p point to the string literal "test".
String literals are read-only. Attempting to modify them will invoke undefined behavior.
If you want "test" to be writable, then you must allocate (writable) memory for it, for example by declaring an array:
char arr[] = "test";
That line is equivalent to
char arr[5] = "test";
which creates an array of 5 characters and initializes the first 4 characters to "test" and initializes the 5th character to a null terminating character.
Now that you have allocated memory for the string, you can write to it at will, for example you could write:
for (int i = 0; i < 4; ++i) {
arr[i] = 50;
}
Or you could make a pointer p point to the array, and use the pointer for accessing the string, as you did in the code in the question:
char *p = arr;
for (int i = 0; i < 4; ++i) {
p[i] = 50;
}

Array returning more characters than allocated with malloc [duplicate]

This question already has answers here:
Extra characters added to end of string in c
(3 answers)
Closed 5 years ago.
I am writing a function in C which takes two strings of the same length,
for example:-
S1 = "Hello" and S2 = "12345"
and returns a result that mixes the characters from the input strings so that the first char in the result string is the first char from S1, the second char is the first char from S2, the third char in r is the second char from S1 and the fourth char in r is the second char from S2, and so on....
So if:-
S1 = "Hello"
S2 = "12345"
Result = "H1e2l3l4o5"
My function looks like this:
#include <stdio.h>
#include <string.h>
char* mix(char *s1, char *s2)
{
int length = strlen(s1);
char* result = malloc(sizeof(char) * length * 2);
int i, j;
for(i = 0, j = 0; i < (length); i++, j = j + 2)
{
result[j] = s1[i];
result[j + 1] = s2[i];
}
return result;
}
For the values of S1 and S2 above it produces:
`H1e2l3l4o5:=C:\Uºt6▄╘º`
Which confuses me as I didn't allocate "result" enough memory for that many chars and wasn't warned of a segmentation fault or anything of that nature. Have I obviously done something wrong?
This happens because you did not null-terminated the string in the result. Add this line to fix this problem:
result[j] = '\0';
Another issue you need to fix is allocating the space for null terminator:
char* result = malloc(length * 2 + 1);
C standard requires sizeof(char) to be 1, so multiplying by it is not necessary.
Finally, you need to make sure that s2 has enough length to be copied into the result, i.e. strlen(s2) >= strlen(1).
You didn't allocate memory for the null character required to terminate a C string and, of course, you didn't put it after the string. This is why the code prints garbage from memory until it reaches the first null character.
char* mix(char *s1, char *s2)
{
int length = strlen(s1);
char* result = malloc(sizeof(char) * (length * 2 + 1));
int i, j;
for(i = 0, j = 0; i < length; i ++, j = j + 2)
{
result[j] = s1[i];
result[j + 1] = s2[i];
}
// Put the null character to end the the string
result[j] = 0;
return result;
}
Apparently the code should also check the length of s2 but, by chance, this is not needed.
If s1 is longer than s2, the null-terminating character of s2 is copied during the loop and the length of the resulting string is 2*strlen(s2). If s2 is longer than s1, the code copies only its first length characters.

Run time error "Segmentation Fault". How to remove it? (I am working in Ubuntu.) [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Getting Segmentation Fault
// reverse a string
#include`<stdlib.h>`
#include`<stdio.h>`
#include`<string.h>`
#include`<math.h>`
int main()
{
char *string = "mohit",t;
int i=0,j;
printf(" %d %d",strlen(string), (strlen(string)/2)+1);
for(i=0,j=(strlen(string)) ; i<(strlen(string)/2)+1 ; i++,j--)
{
printf("\n%d",(int) string);
printf("\n%d",(int) string+5);
printf("\ni string = %c", *(string + i));
printf("\nj string = %c", *(string + j));
t=*(string+i);
*(string+i) = *(string + j);
*(string + j) = t;
}
printf("\n = %s", string);
return 0;
}
String literals are possibly located in a read-only area of memory; it is not allowed to assign a pointer to one to a pointer to non-const char, and thus your manipulations of string cause undefined behaviour. You either say
const char * string = "mohit";
and don't modify the string, or you create an automatic array of chars that you can modify:
char string[] = "mohit";
The latter is what you need in your case.
Also, as a point of style, writing char * s, t; in one line is possibly misleading; it is equivalent to, and should always be replaced by, char * s; char t;.

Resources