Segmentation Fault with Pointers and Strings - c

I am writing a pointer version of the C function strcat. It copies the string t to the end of s. This is my solution:
/* strcat: a pointer version of the strcat (copy string t to the end of s) */
void strcat (char *s, char *t)
{
while (*s++ != '\0') /* find the end of s */
;
while (*s++ = *t++)
;
}
I ran it and it crashed - the Code Blocks debugger called it a segmentation fault, and that this part of the function was causing the crash:
while (*s++ = *t++)
What have I done wrong?

Here is the fixed version and a test program:
#include <stdio.h>
void strcat (char *s, char *t)
{
while (*s++)
;
s--;
while (*s++ = *t++)
;
}
int
main(void)
{
char str1[100] = "abc";
char *str2 = "def";
strcat(str1, str2);
printf("%s\n", str1);
return 0;
}
If you call that strcat() in the following way,
char *str1 = "abc";
char *str2 = "def";
strcat(str1, str2);
then your program may crash, because compilers usually put string literals in read-only memory region, try to write to these places will cause segment fault.

Related

Why am I getting a segmentation fault? C, basic code

Why I am getting a segmentation fault? Unlike other similar questions posted here, it doesn't seem to me that I'm trying to access an array index that is out of memory.
What I want the squeeze(char s1[], char s2[]) function to do, is to delete every char that occurs in s2 from s1 and print the result.
#include <stdio.h>
void squeeze(char s1[], char s2[]);
int main()
{
squeeze("test string", "ts");
return 0;
}
void squeeze(char s1[], char s2[])
{
int i, j, k;
for (k = 0; s2[k] != '\0'; k++) {
for (i=j=0; s1[i] != '\0'; i++)
if (s1[i] != s2[k]) {
s1[j] = s1[i];
++j;
}
s1[j] = '\0';
}
printf("%s", s1);
}
Error occurs on the line s1[j] = s1[i];, when I tried to separate it into two lines and use another char as a placeholder, the segfault was on line with s1[j].
I also tried to use gdb, and I could read both s1[j] and s1[i].
Here is the segfault message from gdb:
Program received signal SIGSEGV, Segmentation fault.
squeeze (s1=0x555555556007 "test string", s2=0x555555556004 "ts") at main.c:18
18 s1[j] = s1[i];
I've recently started learning C, and I have no idea what is the problem.
The C standard does not define the behavior of attempting to write into the array of a string literal. "test string" is a string literal.
Instead of passing it directly to squeeze, define an array of char, initialize that array with the string literal, and pass that array to squeeze:
char buffer[] = "test string";
squeeze(buffer, "ts");
In this call
squeeze("test string", "ts");
you are trying to change a string literal. Though in C opposite to C++ string literals have non-constant character array types nevertheless any attempt to change a string literal results in undefined behavior.
You should declare a character array and initialize it with the string literal as for example
char s1[] = "test string";
squeeze( s1, "ts");
Also the function should be declared like
char * squeeze( char s1[], const char s2[] );
And the used approach is inefficient.
The function can be defined the following way as shown in the demonstrative program below
#include <stdio.h>
#include <string.h>
char * squeeze( char s1[], const char s2[] )
{
if ( *s2 )
{
char *p = s1, *q = s1;
do
{
if ( *p == '\0' || strchr( s2, *p ) == NULL )
{
if ( p != q ) *q = *p;
++q;
}
} while ( *p++ );
}
return s1;
}
int main( void )
{
char s1[] = "test string";
puts( squeeze( s1, "ts" ) );
}
The program output is
e ring

Exercise 5-3. Write a pointer version of the function strcat that we showed in Chapter 2: strcat(s,t) copies the string t to the end of s

Cannot figure out why the program doesn't work when parameters are the same character string.
int main (void) {
char s[] = "123";
strcat(s, s);
return 0;
}
void strcat (char *s, char *t) {
int len = strlen(s);
while (*t != '\0')
*(s + len++) = *t++;
*(s + len) = '\0';
}
You need spare room in the first string to concatenate the second string. And you are modifying the same memory that you are reading from. And as you do, you are removing the termination char so this would likely end up in an infinite loop.

C -swap 2 chars recursively with only one pointer

I need to write a function:
void swap (char * s1, char * s2);
The function will replace the contents of both strings 1s and 2s.
Constraints:
In the function, there is no use of [] anywhere, but performance by working with pointers, in addition, trips must be made with the voters, meaning that they will actually move to another cell as needed, and will not remain in the same location all the time.
• No loops in the function, that is, work in recursion.
I did the function with pointer to pointer str** but must change it to only one pointer str and recursively. How can I change it?
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *str1="abc",*str2="xyz",*pRev;
swap(&str1, &str2);
printf("str1 is %s, str2 is %s", str1, str2);
getchar();
return 0;
}
//need *str NOT **str
void swap(char **str1, char **str2);
char * RevWords (char * str, int size);
void swap(char **str1, char **str2)
{
char *temp = *str1_ptr;
*str1_ptr = *str2_ptr;
*str2_ptr = temp;
}
after swap method:
str2="abc", str1="xyz"
Well this is clearly not an ideal solution but gives you something to work with.
However this will only work (as mentioned above) when you have the same length of strings (or yes, you'll have to allocate memory + you'd need to know the length of your strings). But otherwise I think this may answer your question.
This is working with recursion and depends on the fact that both strings are the same length and containing a zero character at the end of each one.
#include <stdio.h>
#include <stdlib.h>
void swap(char* str1, char* str2)
{
// if both of them are zero characters then stop
if (*str1 == '\0' && *str2 == '\0')
return;
// else swap the contents of the pointers
else
{
char tmp = *str1;
*str1 = *str2;
*str2 = tmp;
// advance both pointer and swap them too if thye are not '\0'
swap(++str1, ++str2);
}
}
int main()
{
char str1[] = "abc\0\0\0"; // padded with zeros to be the same length as str2
char str2[] = "xyz123"; // the last '\0' is automatically added
swap(str1, str2);
printf("str1 is %s, str2 is %s", str1, str2);
getchar();
return 0;
}

Segmentation Fault while trying to copy string in C function

I have a function in 'C' that is supposed to implement my own strcpy program. Here's what I wrote. However, I am not able to debug the cause of Segmentation Fault.
#include <stdio.h>
#include <stdlib.h>
char * mystrcpy(char *dest, char *src) {
char * ptr = dest;
while (*src != '\0'){
*ptr = *src;
ptr++; src++;
//printf("Dest is \"%s\" and Source is \"%s\"\n",dest,src);
}
*ptr = '\0';
return dest;
}
int main() {
char str[] = "I rock always";
char * dest = NULL;
dest = mystrcpy(dest, str);
printf("Source String %s and Destination String %s\n", str, dest);
}
Can someone explain this behavior to me ?
You have to allocate memory for the destination string:
int main() {
char str[] = "I rock always";
char * dest = (char*)malloc(strlen(str) + 1);
dest = mystrcpy(dest, str);
printf("Source String %s and Destination String %s\n", str, dest);
}
Of course, it is good manners to free the memory eventually:
free(dest);
You never allocate any memory for *dest to point to.
It starts pointing to NULL, and then you attempt: *ptr = *src.
#include <stdio.h>
/* this the K&R version of strcpy */
char * mystrcpy(char *dest, char *src) {
char *ptr = dest;
while ( *ptr++ = *src++ ) {;}
return dest;
}
int main(void) {
char str[] = "I rock always";
char dest[sizeof str];
char *result;
result = mystrcpy(dest, str);
printf("Source String %s and Destination String %s and result %s\n", str, dest, result);
return 0;
}
Allocate memory and try....
#include <stdio.h>
#include <stdlib.h>
char * mystrcpy(char *dest, char *src)
{
char * ptr = dest;
int index=0;
while (*src != '\0')
{
*(ptr+index) = *(src+index);
index++;
}
*(ptr+index) = '\0';
return dest;
}
int main()
{
char str[] = "I rock always";
char * dest = (char*)malloc((strlen(str)+1)*sizeof(char));
dest = mystrcpy(dest, str);
printf("Source String %s and Destination String %s\n", str, dest);
free(dest);
return 0;
}
You must allocate memory for the destination string buffer.
Memory management is a very big part of C ... you need to be very careful that you allocate AND deallocate memory as it is used and becomes surplus to requirements. Failure to do so will result in segmentation faults (failing to allocate memory) and memory leaks (failing to free memory)
Other answers here give you examples of malloc so I won't repeat them here.
You should use the functions already available to you as much as possible, rather than writing your own. This avoids errors in implementation as somebody has already debugged and optimized it for you.
http://www.cs.cf.ac.uk/Dave/C/node19.html

Why segmentation fault on implementation of strcpy?

I implement a simple strcpy, but when i run it , it always give a segmentation fault.
Please help!
Below is my code:
#include <stdio.h>
char* mystrcpy(char *dst, char *src){
char *ptr = dst;
while (*src !='\0') {
*dst = *src;
dst++;
src++;
}
return ptr;
}
int main (int argc, char **argv) {
char *str1 = "abc";
char *str2 = "def";
char *str3 = NULL;
str3 = mystrcpy(str2, str1);
printf("str2 now is %s", str2);
printf("str3 is %s", str3);
return 0;
}
These are read-only. Writing to them results in undefined behavior.
char *str1="abc"; /* Read-only. */
char *str2="def";
while (*src !='\0') {
*dst = *src; /* Writes into read-only memory. */
See this C FAQ:
String constants are in fact constant. The compiler may place them in
nonwritable storage, and it is therefore not safe to modify them.
And another explanation. You should try
char str1[]="abc";
char str2[]="def";
while( *src !='\0'){
*dst=*src;
You need to dereference your pointers here, using &, not *
EDIT:
Looks like I'm having my own personal cranial segmentation fault, here - too early in the morning!
cnicutar's explanation (assigning a pointer to a string constant with char *str2 = "def";, and then trying to write to that location) is much more plausible...

Resources