c++ segfault: char pointers [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do you reverse a string in place in C or C++?
Why is this C code causing a segmentation fault?
Modifying value of char pointer in c produces segfault
Running a very simple code example
#include <stdlib.h>
#include <iostream>
char* last_char(char* s){
char* last = s;
while (*last) ++last;
return last;
}
char* in_place_reverse(char* s) {
char* left = s;
char* right = last_char(s);
char temp;
while( left < right ) {
temp = *left;
*left = *right;
*right = temp;
left++;
right--;
}
return s;
}
int main(){
char * s = "letters\n";
std::cout << in_place_reverse(s);
}
All the time I get
Segmentation fault
But from my point of view I'm not doing anything illegal within the code.
Please help me to determine what's wrong.
P.S. I compile with
g++ example.c

Two problems:
You are trying to modify a string literal. This may work, it may not, or it may crash. This is invoking undefined behavior. Use char s[] = "letters\n" to make a mutable copy.
last_char() in fact returns a pointer to the sentinel '\0' at the end of the string -- it points beyond the last character. Change return last to return last - 1. Otherwise you are going to move the sentinel around too, and that's almost certainly not what you want. (Note that this will return a pointer to garbage if the string is zero-length. You should fast-succeed in in_place_reverse() if *s == '\0' to avoid this complexity.)

You are modifying a string literal and string literals are non-modifiable.
Use char s[] = "letters\n"; instead

Related

What is this line of code achieving? What does the incrementation mean? [duplicate]

This question already has answers here:
How does "while(*s++ = *t++)" copy a string?
(17 answers)
Closed last year.
I understand that s and t are both pointers and they are being copied to one another but the incrementing part is confusing to me.
void funct(char *s, char *t){
while( *s++ = *t++ );
}
answer was here
How does "while(*s++ = *t++)" copy a string?
It is equivalent to this:
while (*t) {
*s = *t;
s++;
t++;
}
*s = *t;
When the char that t points to is '\0', the while loop will terminate. Until then, it will copy the char that t is pointing to to the char that s is pointing to, then increment s and t to point to the next char in their arrays.
The function performs a copy of the string the first character of which is pointed to by the pointer t into a character array pointed to by the pointer s using the pointers.
void funct(char *s, char *t){ while( *s++ = *t++ ); }
To make it more clear you can rewrite the while loop the following way
void funct(char *s, char *t)
{
while( ( *s = *t ) != '\0' )
{
s++;
t++;
}
}
The only difference is that the increment of the pointers in the last while loop is performed in the body of the while loop if the copied character is not the terminating zero character '\0' of the string pointed to by the pointer t.
That is characters pointed to by the pointer t are assigned to characters pointed to by the pointer s. If the current copied character is equal to the terminating zero character then the condition of the loop evaluates to false. As a result one string is copied in another character array.

Modifying a c string [duplicate]

This question already has answers here:
Access violation writing location when working with pointers to char
(4 answers)
Closed 5 years ago.
I'm trying to implement tolower(char *) function, but I get access violation error. I came to know that this is because to compiler stores string literals in a read-only memory. Is this true?
Here's some code:
char* strToLower(char *str)
{
if(str == nullptr)
return nullptr;
size_t len = strlen(str);
if(len <= 0)
return nullptr;
for(size_t i = 0; i < len; i++)
*(str+i) = (char)tolower(*(str+i));//access violation error
return str;
}
int main()
{
char *str = "ThIs Is A StRiNgGGG";
cout << strToLower(str) << endl;
system("pause");
return 0;
}
If this is true, how am I supposed to implement such function?
Yes, it's true. You cannot modify a string literal. In fact, if your compiler were not from 1922 it would have prevented you from even obtaining a non-const pointer to a string literal in the first place.
You didn't state your goals, so when you ask "how am I supposed to implement such function" it's not really clear what you want to do. But you can make a copy of the string literal to get your own string, then modify that as you please:
// Initialises an array that belongs to you, by copying from a string literal
char str[] = "ThIs Is A StRiNgGGG";
// Obtains a pointer to a string literal; you may not modify the data it points to
const char* str = "ThIs Is A StRiNgGGG";
// Ancient syntax; not even legal any more, because it leads to bugs like yours
char* str = "ThIs Is A StRiNgGGG";
Of course, since this is C++, you should not be using C-strings in the first place:
std::string str("ThIs Is A StRiNgGGG");

strstr not working in C++ 4.7 on codeforces

On online compiler this program is giving perfect output on giving input "ABACABA", but on Codeforces tests it is just posting the last line. On debugging I found out that the pointer u is indicating to address 0 when strstr() is used. I am unable to understand why the function is working on other online compiler ,but not on Codeforces.
EDIT: Okay so thanks to #Jeremy Friesner, I found out that it is actually strncpy that is not working properly because now the custom test cases compiler is giving wrong output for 'str'. Still don't know why it should behave differently on two different compilers and what changes should I make.
#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<stdlib.h>
using namespace std;
int main()
{
char *s;
int length=20;
s = (char *) malloc(length*(sizeof(char)));
char c;
int count=0;
while((c=getchar())>='A')
{
if(c<='Z')
{
//cout<<count;
if(length>=count)
{
s = (char *) realloc(s,(length+=10)*sizeof(char));
}
s[count++]=c;
//printf("%p\n",s);
}
else
{
break;
}
}
char *u=s;
int o=1;
//printf("%p\n",s);
while(u)
{
char *str = (char *) malloc(o*sizeof(char));
str = strncpy(str,s,o);
//cout<<str<<endl;
char *t;
u = strstr(s+1,str);
//printf("u %p\n",u);
t=u;
int ct=0;
char *p;
while(t)
{
ct++;
p=t;
t = strstr(t+o,str);
}
ct=ct+1;
//cout<<"here"<<endl;
if(p==(s+count-o))
{
cout<<o<<" "<<ct<<endl;
}
//cout<<ct<<endl;
o++;
}
cout<<count<<" "<<1;
}
As noted in the comments, a principal problem was that you were not null-terminating the string after you read it in, which leads to odd results. Specifically, it leads to you invoking undefined behaviour, which is always a bad thing. The memory allocated by malloc() and the extra memory allocated by realloc() is not guaranteed to be zeroed.
You can fix the problem by adding:
s[count] = '\0';
just before:
char *u = s;
Strictly, you should also check the return values of both malloc() and realloc(). Also, you should not use the idiom:
x = realloc(x, newsize);
If the realloc() fails, you've lost your pointer to the original data, so you've leaked memory. The safe way to work is:
void *space = realloc(x, newsize);
if (space == 0)
…report error etc…
x = space;
x_size = newsize;
There may be other problems; I've not scrutinized the code for every possible issue.
You never put null-termination after the characters you put into s, therefore s does not contain a string. So it causes undefined behaviour to pass it to a function that expects a string, such as strncpy.
Another big problem is your usage of strncpy.
int o=1;
while(u)
{
char *str = (char *) malloc(o*sizeof(char));
str = strncpy(str,s,o);
u = strstr(s+1,str);
The strncpy function does not create a string, if strlen(s) >= o. In this case, the strstr function will just read off the end of the buffer, causing undefined behaviour. (Exactly what happens will depend on your compiler and on what junk was in this piece of memory).
You need to put a null-terminated string into str. Either manually add a null-terminator:
assert(o > 0);
strncpy(str, s, o-1);
str[o-1] = 0;
or use a different function:
snprintf(str, o, "%s", s);
You have to keep in mind that a string is a series of characters followed by a null terminator. Whenever you work with functions that expect strings, it's up to you to make sure that the null terminator is present.
Also be careful with lines like strstr(t+o,str);. If o > strlen(t) this causes undefined behaviour. You've got to do the checking yourself that you do not go outside the bounds of the string.

Access violation error when reversing a string c++ [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why do I get a segmentation fault when writing to a string?
The following simple function should reverse a character array in place.
void reverse(char* str)
{
char* last = str;
// find end of the string
while(*last) {
++last;
}
// swap characters until the pointers meet in the middle
while(str < last)
{
--last;
char temp = *str;
*str = *last;
*last = temp;
++str;
}
}
int main()
{
char* a= "Hello";
reverse(a);
return 0;
}
The code compiles. But it throws a runtime error about access violation. According to the debugger the culprit is the line below:
char temp = *str;
Any ideas why it happens?
char* a= "Hello";
The pointer a points to a string literal. According to the standard, attempting to modify a string literal results in undefined behaviour. In the case of your implementation, the segmentation fault indicates that the compiler is choosing to place the string literal in non-modifiable memory.
Declare a to be a string that is modifiable. For example, like this:
char a[] = "Hello";

Segmentation fault in equating a char pointer value to some char [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Why is this C code causing a segmentation fault?
char* string = "abcd";
now when i try to change some character of this string i get segmentation fault
*string = 'p';
or
string[0] = 'p';
string[0] = 52;
Can someone please explain me the reason that why is it happening.
Thanks
Alok.Kr.
If you write char* string = "abcd"; the string "abcd" is stocked into the static data part of your memory and you can't modify it.
And if ou write char* string = 'p';, that's just wrong. First, you try to declare a variable with the same name (string) and, worse, you try to assign a char value to a char pointer variable. This doesn't work. Same thing : char[0] = 'p'; really means nothing to your compiler except a syntax error.
String literals are non-modifiable in C. This has been asked and answered many times before, though it isn't too easy to search for.
If you want to modify string, declare it as an array, not a pointer to a string literal.
#include <stdio.h>
int main()
{
char string[] = "hello world";
string[0] = 'H';
string[6] = 'W';
printf("%s\n", string);
return 0;
}
Results in:
$ /tmp/hello
Hello World