Test program which causes a EXC_BAD_ACCESS signal.
Why does this cause a bus error? I want to change the 'HI' to 'fI'.
//BUS ERROR TEST
#include <iostream>
void test(char *text)
{
text[0] = 'f';
}
int main()
{
char *text = (char *)"HI";
test(text);
std::cout << text << std::endl;
return 0;
}
You are not allowed to change string constants, that's undefined behaviour as per the standard.
If you replace:
char *text = (char *)"HI";
with something like:
char text[3];
strcpy (text, "HI");
or:
char text[] = "HI";
you'll find that it will work, because text in that case is modifiable memory.
You must not cast away const, it's UB. The string constants are read-only, so the compiler is allowed to put them into read-only memory.
Use
char text[] = "Hi!";
to get a modifiable string.
char *text = (char *)"HI";
text[0] = 'f';
This is actually against the C++ standard. Quoted strings are declared const for a reason. In your case, it probably stores the string as part of your "code data" rather than regular "data". This, combined with the common usage of making the "code data" area read only makes it so that you won't be able to write to quoted constant strings.
Related
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";.
I couldn't believe that I couldn't get this right! Someone please help!
This says word is being used without being initialised(Is that required?):
int main(int argc, char* argv[])
{
char* word;
sprintf(word,"%d",12);
std::cout << word;
return 0;
}
And if I were to do this, it gives DEBUG ASSERTION FAILED!:
int main(int argc, char* argv[])
{
char* word = NULL; // char* word = nullptr;
sprintf(word,"%d",12);
std::cout << word;
return 0;
}
I have included stdio.h header. It is not making sense how I am fumbling over this.
You need to initialize it with allocated memory.
char word[20];
or
char* word = new char[20];
Initializing it to NULL will make it crash as the function tries to write at this address. Not initializing it will be undefined behavior as well since the address will be garbage.
Both those code snippets are undefined behavior.
In the first, the pointer word is uninitialized, so its value is indeterminate (and will seem to be random), so when using to write data you don't know where it will be written.
The second will always write to address zero, which is also undefined behavior.
The solution to this is to remember that you are using C++, which have std::string:
std::string word;
word = "12";
Or if you have the number as an integer that you want to use, then look at std::ostringstream:
int value = 12;
// ...
std::ostringstream os;
os << value;
std::string word = os.str();
You are declaring word as a pointer: to what?
If you need a string, and you still want to use sprintf, you have to declare its length:
char word[20]; // twenty bytes including string terminator \0
This fixed-length syntax is prone to errors and nowadays obsolete: please refer to #Joachim Pileborg answer for a better use of strings in C++
I want to copy a char to an address where a given char* points to.
it's in a function which is called by main:
char data = " ";
myfunction(data, somethingelse);
...
inside the function i have something like
void myfunction(char* data, short somethingelse) {
...
char byte = 0;
inputfilestream.read(&byte, 1);
*data = byte; // here i get the segfault
data++;
...
}
the segfault also comes when i to the copy using strncpy:
strncpy(data, byte, 1);
why is there a segfault? data isn't const and the address where i actually write to is exactly the same as the one where i allocated the data-array. i've tested that multiple times.
thanks in advance.
String literals are readonly. If you want a modifyable string, you must use an array, e.g.:
char data[10];
Or:
char *data = new char[10];
To elaborate a bit more: the type of a string literal is actually const char*. Assigning a string literal to a non-const char* is therefore technically invalid, but most compilers allow it anyway for legacy reasons. Many modern compilers will at least issue a warning when you try to do that.
data is assigned a string literal. String literals are ready only, and writing to them will cause segfaults.
Try this:
char data[10]; // or whatever size you want.
instead.
why is there a segfault? data isn't const and the address where i actually write to is exactly the same as the one where i allocated the data-array.
You didn't allocate anything. char *data = " "; shouldn't even compile in C++. You are assigning a constant string to a non-constant.
char byte = 0;
inputfilestream.read(&byte, 1);
*data = byte; // here i get the segfault
data++; // << How many times?
No problem
#include <stdio.h>
int main(int argc, char **argv)
{
char *data = "Yello"; // or char data[] = "Yello";
*data = 'H';
puts(data); // Hello
}
I'm currently using
char *thisvar = "stringcontenthere";
to declare a string in C.
Is this the best way to declare a string in C?
And how about generating a C-String from C++-Strings?
In C it depends on how you'll use the string:
named constant: your char* str = "string"; method is ok (but should be char const*)
data to be passed to subfunction, but will not not used after the calling function returns:
char str[] = "string";
data that will be used after the function it is declared in exits: char* str = strdup("string");, and make sure it gets freed eventually.
if this doesnt cover it, try adding more detail to your answer.
As other suggested, and I you want to "do it" the C++ way, use a std::string.
If you somehow need a C-string, std::string has a method that gives a const char*.
Here is an example:
#include <iostream>
#include <string>
void dummyFunction(const char* str)
{
// Do something
}
int main(int, char**)
{
std::string str = "hello world!";
dummyFunction(str.c_str());
return EXIT_SUCCESS;
}
const char *thisvar="stringcontenthere";
It depends. For ASCII encoded strings see paragraphs C and C++. For unicode encoded strings see last paragraph.
C:
As David pointed out it depends on how to use the string in C:
as a constant then: const char s[] = "Hello World";
as a string containing variable data then: char s[] = "Hello World";
as a data array char *data; Initialization then should be customized.
Please note in C there are all Strings Null-terminated, that means the definition of e.g. char s[] = "foo"; implicitly includes a NULL character at the end s[3]='\0'.
Also please note the subtile difference between char *s and char s[] which might often behave the same but sometimes not! (see Is an array name a pointer?) for example:
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char* argv[])
{
char s[] = "123456789123456789123456789";
char *t = (char*) malloc( sizeof(char) * 28 );
for( size_t i = 0; i < 28; ++i )
t[ i ] = 'j';
printf( "%lu\n", sizeof(s) );
printf( "%lu\n", sizeof(t) );
printf( "%s\n", s );
printf( "%s\n", t );
return EXIT_SUCCESS;
}
So I recommend to use char arrays whenever you use them as strings and char pointers whenever you use them as data array.
C++:
In C++ there is an own string data type: std::string. If you just need to have a C-String version of a std::string (e.g. using some C-API) just use the c_str() member:
std::string s = "Hello World";
your_c_call( s.c_str(), ... );
Unicode:
I you want to have unicode strings then you should really go with something like
char utf8String[] = u8"Hello World";
and try not to use wchar_t whenever possible. See this excellent article on that issue: http://www.nubaria.com/en/blog/?p=289. Please not that there is also unicode support for C++. But generally I am tempted to say that you should go with normal characters as far as you can. Interesting resource on that: http://www.cprogramming.com/tutorial/unicode.html
Is this C or C++? In C++ you should use std::string:
std::string aString("stringcontenthere");
I have a class with a private char str[256];
and for it I have an explicit constructor:
explicit myClass(char *func)
{
strcpy(str,func);
}
I call it as:
myClass obj("example");
When I compile this I get the following warning:
deprecated conversion from string constant to 'char*'
Why is this happening?
This is an error message you see whenever you have a situation like the following:
char* pointer_to_nonconst = "string literal";
Why? Well, C and C++ differ in the type of the string literal. In C the type is array of char and in C++ it is constant array of char. In any case, you are not allowed to change the characters of the string literal, so the const in C++ is not really a restriction but more of a type safety thing. A conversion from const char* to char* is generally not possible without an explicit cast for safety reasons. But for backwards compatibility with C the language C++ still allows assigning a string literal to a char* and gives you a warning about this conversion being deprecated.
So, somewhere you are missing one or more consts in your program for const correctness. But the code you showed to us is not the problem as it does not do this kind of deprecated conversion. The warning must have come from some other place.
The warning:
deprecated conversion from string constant to 'char*'
is given because you are doing somewhere (not in the code you posted) something like:
void foo(char* str);
foo("hello");
The problem is that you are trying to convert a string literal (with type const char[]) to char*.
You can convert a const char[] to const char* because the array decays to the pointer, but what you are doing is making a mutable a constant.
This conversion is probably allowed for C compatibility and just gives you the warning mentioned.
As answer no. 2 by fnieto - Fernando Nieto clearly and correctly describes that this warning is given because somewhere in your code you are doing (not in the code you posted) something like:
void foo(char* str);
foo("hello");
However, if you want to keep your code warning-free as well then just make respective change in your code:
void foo(char* str);
foo((char *)"hello");
That is, simply cast the string constant to (char *).
There are 3 solutions:
Solution 1:
const char *x = "foo bar";
Solution 2:
char *x = (char *)"foo bar";
Solution 3:
char* x = (char*) malloc(strlen("foo bar")+1); // +1 for the terminator
strcpy(x,"foo bar");
Arrays also can be used instead of pointers because an array is already a constant pointer.
Update: See the comments for security concerns regarding solution 3.
A reason for this problem (which is even harder to detect than the issue with char* str = "some string" - which others have explained) is when you are using constexpr.
constexpr char* str = "some string";
It seems that it would behave similar to const char* str, and so would not cause a warning, as it occurs before char*, but it instead behaves as char* const str.
Details
Constant pointer, and pointer to a constant. The difference between const char* str, and char* const str can be explained as follows.
const char* str : Declare str to be a pointer to a const char. This means that the data to which this pointer is pointing to it constant. The pointer can be modified, but any attempt to modify the data would throw a compilation error.
str++ ; : VALID. We are modifying the pointer, and not the data being pointed to.
*str = 'a'; : INVALID. We are trying to modify the data being pointed to.
char* const str : Declare str to be a const pointer to char. This means that point is now constant, but the data being pointed too is not. The pointer cannot be modified but we can modify the data using the pointer.
str++ ; : INVALID. We are trying to modify the pointer variable, which is a constant.
*str = 'a'; : VALID. We are trying to modify the data being pointed to. In our case this will not cause a compilation error, but will cause a runtime error, as the string will most probably will go into a read only section of the compiled binary. This statement would make sense if we had dynamically allocated memory, eg. char* const str = new char[5];.
const char* const str : Declare str to be a const pointer to a const char. In this case we can neither modify the pointer, nor the data being pointed to.
str++ ; : INVALID. We are trying to modify the pointer variable, which is a constant.
*str = 'a'; : INVALID. We are trying to modify the data pointed by this pointer, which is also constant.
In my case the issue was that I was expecting constexpr char* str to behave as const char* str, and not char* const str, since visually it seems closer to the former.
Also, the warning generated for constexpr char* str = "some string" is slightly different from char* str = "some string".
Compiler warning for constexpr char* str = "some string": ISO C++11 does not allow conversion from string literal to 'char *const'
Compiler warning for char* str = "some string": ISO C++11 does not allow conversion from string literal to 'char *'.
Tip
You can use C gibberish ↔ English converter to convert C declarations to easily understandable English statements, and vice versa. This is a C only tool, and thus wont support things (like constexpr) which are exclusive to C++.
In fact a string constant literal is neither a const char * nor a char* but a char[]. Its quite strange but written down in the c++ specifications; If you modify it the behavior is undefined because the compiler may store it in the code segment.
Maybe you can try this:
void foo(const char* str)
{
// Do something
}
foo("Hello")
It works for me
I solve this problem by adding this macro in the beginning of the code, somewhere. Or add it in <iostream>, hehe.
#define C_TEXT( text ) ((char*)std::string( text ).c_str())
I also got the same problem. And what I simple did is just adding const char* instead of char*. And the problem solved. As others have mentioned above it is a compatible error. C treats strings as char arrays while C++ treat them as const char arrays.
For what its worth, I find this simple wrapper class to be helpful for converting C++ strings to char *:
class StringWrapper {
std::vector<char> vec;
public:
StringWrapper(const std::string &str) : vec(str.begin(), str.end()) {
}
char *getChars() {
return &vec[0];
}
};
The following illustrates the solution, assign your string to a variable pointer to a constant array of char (a string is a constant pointer to a constant array of char - plus length info):
#include <iostream>
void Swap(const char * & left, const char * & right) {
const char *const temp = left;
left = right;
right = temp;
}
int main() {
const char * x = "Hello"; // These works because you are making a variable
const char * y = "World"; // pointer to a constant string
std::cout << "x = " << x << ", y = " << y << '\n';
Swap(x, y);
std::cout << "x = " << x << ", y = " << y << '\n';
}