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");
Related
Please note that's just a curious question, I don't need a problem solution!
I have a method that takes in a string reference (string &some_string) and only reads from referenced string. Writing some code I forgot that it needs a reference and passed a quoted string (not a variable, just like "something") and IDE suggested casting it to string reference, as it won't compile. I didn't give it a thought and applied the suggestion (now passing (string &) "something"). And my program crashed as it reached this piece of code. So, why exactly would it cause a crash, compiling without even a warning (g++, c++11)? I don't really understand it since I'm only reading from this string.
Example:
#include <string>
#include <iostream>
using namespace std;
class CharSet
{
private:
const string basis = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const int N = 26;
string array; // string containing all element of the set
int length;
bool add_element(char chr) // Add an element (as char) if not already. Returns true if added, false if not.
{
bool b = false;
if (!in_set(chr) && basis.find(chr) != string::npos) {
array += chr;
length++;
b = true;
}
return b;
}
bool in_set(char chr) const // Checks whether an element (as char) is in set. Returns corresponding bool value.
{
bool b = false;
if (array.find(chr) != string::npos) b = true;
return b;
}
public:
explicit CharSet(string& str) // str - string of possible elements
{
array = "";
length = 0;
int len = (int) str.length();
for (int i = 0; i < len; i++)
add_element(str[i]);
if (str.length() != length)
cout << "\nSome mistakes corrected. Elements read: " << array << endl;
}
};
int main()
{
CharSet A((string &)"AKEPTYUMRX");
getchar();
return 0;
}
A cast like this
(string)"a string literal"
constructs a new std::string by passing "a string literal" as an argument to its constructor. It is equivalent to static_cast<std::string>("a string literal"). It is completely valid, even though C-style casts in C++ are a bad idea in general.
On the other hand, a cast like this
(string&)"a string literal"
constructs a reference to an std::string object that resides at the same location as the string literal. Since there is no such object at that location, using this reference results in undefined behaviour (often expressed as a crash). This cast is equivalent to reinterpret_cast<std::string&>("a string literal"). You might know that reinterpret_cast is dangerous and should be avoided as much as possible. With reinterpret_cast, the compiler trusts the programmer nearly totally, which is not really a wise thing to do, but such is the C++ way.
For your function to be able to accept a string literal, it should have a const std::string& parameter, or perhaps better, if you are using C++17, an std::string_view.
void changeArray(char* str1) {
str1[0] = 'f';
}
int main() {
char* msg1 = "andrew";
changeArray(msg1);
cout << msg1 << endl;
return 0;
}
Hi guys,i dont understand why i'm getting segmentation fault. pointers cannot be accessed by index inside functions? (C++)
You're trying to modify string literal, which leads to undefined behavior.
Attempting to modify a string literal results in undefined behavior: they may be stored in read-only storage (such as .rodata) or combined with other string literals:
const char* pc = "Hello";
char* p = const_cast<char*>(pc);
p[0] = 'M'; // undefined behavior
And, char* msg1 = "andrew"; is not allowed since C++11,
In C, string literals are of type char[], and can be assigned directly to a (non-const) char*. C++03 allowed it as well (but deprecated it, as literals are const in C++). C++11 no longer allows such assignments without a cast.
You can construct and pass a char array instead.
String literals can be used to initialize character arrays. If an array is initialized like char str[] = "foo";, str will contain a copy of the string "foo".
E.g.
int main() {
char msg1[] = "andrew";
changeArray(msg1);
cout << msg1 << endl;
return 0;
}
In int main() you declared msg1 as a pointer to a char, not as an array of chars. Do this: char msg1[] = "andrew";.
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";
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why do I get a segmentation fault when writing to a string?
I am new to C/C++, I'm trying to learn it, I have created the following function but it throws an exception, when I'm trying to assign the uppercase value to *string: Unhandled exception at 0x00411820 in CPP1.exe: 0xC0000005: Access violation writing location 0x00417754.
void ToUpper(char* string)
{
while(*string != '\0')
{
if(*string >= 97 && *string <= 122)
{
int symbol = *string;
*string = symbol - 32;
}
string++;
}
}
Usage:
char* x = "text";
ToUpper(x);
Could you please help me?
change
char* x = "text";
to
char x[] = "text";
DONE
Never try to change a const character string. Always use character arrays for this sort of manipulation.
Memory for "text" will be allocated in .readonly section.
char* x = "text";
Tyring to alter read-only section is undefined behaviour.
use gcc -S filename.c to view the assembly code. This gives you more idea about whereabouts of "text".
Like others suggested, I suggest to use char x[] = "text" instead.
main()
{
char *a = "text";
char *x = malloc(strlen(a)+1);
strcpy(x,a);
ToUpper(x);
// ToUpper(a); // Fails
printf("%s %s\n",a,x);
}
Output: text TEXT
ToUpper(a) fails, because the string is replaced in a protected memory area (in the middle of the code most likely, as at least 64-bit x86-processors have [rip] -relative addressing mode, which makes it lucrative to place data in between code lines...
Also char x[]="text"; works, because now the complete array of x is placed in the stack. In case of char *x = "text"; only the pointer is placed on stack, but the content points to restricted (read-only) memory.
It is an error to try to modify a string literal by a pointer:
void f()
{
char * p = "Naee";
p[2] = 'm'; // error: assignment to const; result is undefined
}
Having string literals constant allows for significant optimizations in the storage allocation and access. If you want a string that you can modify
modify, you must copy the characters into an array:
void f()
{
char p [] = "Eero";
p [0] = 'Z'; // ok
}
You can use like this no need to create symbol varible
*string=*string-32;
but pass array to the function in calling environment rather passing string literal
so
char * str[] ="hello";
ToUpper(str);
You have to type cast the value in the assignment statement.
*string = *(char *)symbol - 32;
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