Memory fault and pointer to string - c

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.

Related

C String Length using null

I know the C language has dynamic length strings whereby it uses the special character null (represented as 0) to terminate a string - rather than maintaining the length.
I have this simple C code that creates a string with the null character in the fifth index:
#include <stdio.h>
#include <stdlib.h>
int main () {
char * s= "sdfsd\0sfdfsd";
printf("%s",s);
s[5]='3';
printf("%s",s);
return 0;
}
Thus, a print of the string will only output up to the fifth index. Then the code changes the character at the fifth index to a '3'. Given my understanding, I assumed it would print the full string with the 3 instead of the null, as such:
sdfsdsdfsd3sfdfsd
but instead it outputs:
sdfsdsdfsd
Can someone explain this?
This program exhibits undefined behavior because you modify a read-only string literal. char* s = "..." makes s point to constant memory; C++ actually disallows pointing non-const char* to string literals, but in C it's still possible, and we have to be careful (see this SO answer for more details and a C99 standards quote)
Change the assignment line to:
char s[] = "sdfsd\0sfdfsd";
Which creates an array on the stack and copies the string to it, as an initializer. In this case modifying s[5] is valid and you get the result you expect.
String literals can not be changed because the compiler put the string literals into a read-only data-section (but this might vary by underlying platform). The effect of attempting to modify a string literal is undefined.
In your code:
char * s= "sdfsd\0sfdfsd"
Here, s is char pointer pointing to a string "sdfsd\0sfdfsd" stored in read-only memory, making it immutable.
Here you are trying to modify the content of read-only memory:
s[5]='3';
which leads to undefined behavior.
Instead, you can use char[]:
#include <stdio.h>
int main () {
char a[] = "sdfsd\0sfdfsd";
char * s = a;
printf("%s",s);
s[5]='3';
printf("%s\n",s);
return 0;
}
This operation has failed:
s[5] = 3;
You're trying to change a string literal, which is always read-only. My testing shows the program exited with segfault:
Segmentation fault (core dumped)
You should store it in an array (or allocated memory) before any attempts to change it:
char s[] = "sdfsd\0sfdfsd";
With the above change, the program works as intended.
#include <stdio.h>
int main(){
char x[10] = "aa\0a";
x[2] = '1';
puts(x);
printf("\n\n\nPress any key to exit...");
getch();
return 0;
}
Output: aa1a

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.

string handling in c using pointers

I have written the following program (it is given as an example in one of the best text books). When I compile it in my Ubuntu machine or at http://www.compileonline.com/compile_c_online.php, I get "segmentation fault"
The problem is with while( *p++ = *str2++)
I feel it is a perfectly legal program. Experts, please explain about this error.
PS: I searched the forum, but I found no convincing answer. Some people even answered wrong, stating that *(unary) has higher precedence than ++ (postfix).
#include <stdio.h>
#include <string.h>
int main()
{
char *str1= "Overflow";
char *str2= "Stack";
char *p = str1;
while(*p)
++p;
while( *p++ = *str2++)
;
printf("%s",str1);
return 0;
}
Thanks
str1 and str2 point to string literals. You aren't allowed to modify those. Even if you could, there isn't enough memory allocated for the string to hold the characters you're trying to append. Instead, initialize a sufficiently large char array from a string literal:
char str1[14] = "Overflow";
I feel it is a perfectly legal program.
Unfortunately, it is not. You have multiple, severe bugs.
First of all, you are creating pointers to string literals char *str1= "Overflow"; and then you try to modify that memory. String literals are allocated in read-only memory and attempting to write to them results in undefined behavior (anything can happen).
Then you have while(*p) ++p; which looks for the end of the string, to find out where to append the next one. Even if you rewrite the pointers to string literals into arrays, you don't have enough free memory at that location. You must allocate enough memory to hold both "Overflow" and "Stack", together with the string null termination.
You should change your program to something like this (not tested):
#include <stdio.h>
int main()
{
char str1[20] = "Overflow"; // allocate an array with enough memory to hold everything
char str2[] = "Stack"; // allocate just enough to hold the string "Stack".
char *p1 = str1;
char *p2 = str2;
while(*p1)
++p1;
while(*p1++ = *p2++)
;
printf("%s",str1); // should print "OverflowStack"
return 0;
}
Or of course, you could just #include <string.h> and then strcat(str1, str2).
Because you are crossing the string boundary of Overflow (str1) is why you are getting sigsegv.
str1 does not have enough memory allocated to accomodate beyond Overflow.

Segmentation fault (core dumped) using char*

i am new to c programming. i am getting Segmentation fault (core dumped) when i am
trying to print the string. please help.
#include <stdio.h>
#include <string.h>
int main()
{
char *ptr;
strcpy(ptr, "mystring");
printf( "%s\n", ptr);
return 0;
}
You haven't allocated any memory for your pointer to point at.
char array[MAX_LEN + 1];
char *ptr = array;
strncpy(ptr, "Cadence", MAX_LEN);
ptr[MAX_LEN] = '\0';
printf( "%s\n", ptr);
Please note that strncpy() can be a safer way to copy strings, since we specify the maximum number of characters to copy, which makes it harder to overrun the string and 'scribble' memory.
Update in response to comments: I've altered the above code to use a slightly safer pattern. You might also want to investigate strlcpy() (non-standard library).
When you declare char *ptr;, you allocate memory for a pointer to a char. But if you want to put a string inside the char, it will make an overflow.
Therefore, you have to allocate memory for your string :
char str[1024]; // which is the maximum string lenth that you will be able to put in str.
Furthemore, don't forget the null terminator (\0) that terminate every string and has the size of one char

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