I am having problems when using the strcat function in C++.
If I do :
MyClass::MyClass(char* myString){
char* AnotherString = myString;
strcat(AnotherString, "bob");
}
Then everything is fine. However, if I do:
MyClass::MyFunction(){
char* AnotherString = "fred";
strcat(AnotherString, "bob");
}
I get an unhandled exception in strcat.asm. Any ideas?
Regards
The answer you need...
is to use C++:
std::string anotherString = "fred";
anotherString += "bob";
The answer you probably want...
is what both Let_Me_Be and Moo-Juice said, combined.
This bit of code:
char* anotherString = "fred";
is extremely dangerous and should by all means be avoided. fred is stored in a read-only section of the memory and cannot be changed -- it is essentially the same as a const char* for all pratical purposes. Note that char anotherString[] = "fred"; is a whole different story, as it actually stores a copy of fred, which can be modified at will.
However, as Moo-Juice pointed out, strcat concatenates the second argument after the first one, which means the first string must have enough allocated room to hold both of them. So in your case, char anotherString[] = "fred"; would do you no good, as anotherString would only be 5 bytes long. You should then write:
char anotherString[8] = "fred"; // fred + bob + 1
strcat(anotherString, "bob");
Of course, in a real world scenario you probably don't know the string sizes in advance, so you'd use malloc to allocate an adequated buffer.
The buffer pointed to by "dest" in strcat(dest, src) must be large enough to hold the resulting string. So:
char* anotherString = "fred"; // 5 bytes including zero-terminator
e.g, no room for "Bob".
But, you've posted this in C++ so why are you using strcat() anyway?
#include <string>
std::string another = "fred";
another.append("bob");
First, the compiler shouldn't allow you to compile this (without warnings):
char* str = "fred";
The correct code is:
const char* str = "fred";
String literals are constants, therefore you can't modify their contents.
Related
When I try to convert
char abc[65536];
std::string str; //= "abc";
std::copy(str.begin(), str.end(), abc); // abc = "abcÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ..."
When I to copy the value of str into abc, I'm getting ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ.. in addition.
How do I fix this please?
string has a constructor that accepts char*, so:
std::string str(abc);
edit: oh you changed the question. Your problem is with null termination.
str has 3 characters. copy copies these 3 characters. This means abc is not (yet) null-terminated. So you don't know where the end of the string is.
try
abc[str.length()] = 0;
to null-terminate it.
I would also recommend dynamically allocating this memory because 1. 64kb on the stack is a lot, and 2. you are setting yourself up for a hard-to-find disaster and/or security holes by making assumptions about a string size.
If you can use const char *, then consider just using str.c_str() to access the underlying array.
There is no need to use std::copy. Simply call the c_str() method on std::string.
char * cstr = new char [str.length()+1];
std::strcpy (cstr, str.c_str());
you can use strcpy(abc,str.c_str()), this will copy the string from str to abc.
Code:
const char* copyoutmsg(unsigned char instring[2055])
{
char* msg = "";
const char* wholestring = reinterpret_cast<const char*>(instring);
strncpy(msg,wholestring,eotpos-5);
printf("Message: %s\n",msg);
return msg;
}
It's seg faulting (process returning 139) - can't get my head round it. Eotpos is the position of the end of the message. What this function is meant to do is input an unsigned char array, convert it to const char and return the message minus 5 chars from the end. I cannot see what is causing this.
Ignoring all other problems in your code, segfault source is in these statements:
char* msg = "";
const char* wholestring = reinterpret_cast<const char*>(instring);
strncpy(msg,wholestring,eotpos-5);
You're trying to copy the string pointed by wholestring into a memory location where msg is pointing to. msg is pointing in the read-only part of the memory, where the string literals are stored (see the first statement of your code). You need to allocate memory for the message first:
char* msg = new char[eotpos - 5 + 1];
const char* wholestring = reinterpret_cast<const char*>(instring);
strncpy(msg,wholestring,eotpos-5);
Don't forget to delete memory afterwards!
Note that you cannot initialize a char* from a string literal in C++11. The clause which allowed that initialization in C++98 and C++03 was removed. If you worked out why that is, you have a hint on one thing which went wrong! You may want to read up on memory allocation as well or, better yet, use proper C++ facilities like std::string as raw pointer manipulators are fairly hard to get right.
I might be wrong, but you don't allocate any memory for msg, of course it will segfault if you try to copy a string to it.
Besides, if eotpos is the position of the last message character (and it does not point to the string termination literal), the message has the length of eotpos+1 (without the string termination literal), since the counting starts with 0. That is why you will have to allocate eotpos+1-5+1 characters for msg (the last +1 is being used for the string termination literal).
Initialize msg like this:
char* msg = malloc(eotpos-3); // Or new char[eotpos - 3], when I answered, there was still just the C tag
msg[eotpos-4] = 0;
And then copy:
strncpy(msg,wholestring,eotpos-4);
Well, depending on what eotpos really is, you have to fix the constant values above. But in my opinion, your description is a little value.
If i define something like below,
char *s1 = "Hello";
why I can't do something like below,
*s1 = 'w'; // gives segmentation fault ...why???
What if I do something like below,
string s1 = "hello";
Can I do something like below,
*s1 = 'w';
Because "Hello" creates a const char[]. This decays to a const char* not a char*. In C++ string literals are read-only. You've created a pointer to such a literal and are trying to write to it.
But when you do
string s1 = "hello";
You copy the const char* "hello" into s1. The difference being in the first example s1 points to read-only "hello" and in the second example read-only "hello" is copied into non-const s1, allowing you to access the elements in the copied string to do what you wish with them.
If you want to do the same with a char* you need to allocate space for char data and copy hello into it
char hello[] = "hello"; // creates a char array big enough to hold "hello"
hello[0] = 'w'; // writes to the 0th char in the array
string literals are usually allocated in read-only data segment.
Because Hello resides in read only memory. Your signature should actually be
const char* s1 = "Hello";
If you want a mutable buffer then declare s1 as a char[]. std::string overloads operator [], so you can index into it, i.e., s1[index] = 'w'.
Time to confuse matters:
char s0[] = "Hello";
s0[0] = 'w';
This is perfectly valid! Of course, this doesn't answer the original question so here we go: string literals are created in read-only memory. That is, their type is char const[n] where n is the size of the string (including the terminating null character, i.e. n == 6 for the string literal "Hello". But why, oh, why can this type be used to initialize a char const*? The answer is simply backward compatibility, respectively compatibility to [old] C code: by the time const made it into the language, lots of places already initialized char* with string literals. Any decent compiler should warn about this abuse, however.
I am trying to append two chars but for some reason I am getting a segmentation fault.
My code is like;
#include <string.h>
char *one = (char*)("one");
char *two = (char*)("two");
strcat(one, two);
and I seem to be getting a segmentation fault at strcat(one, two), why is that?
http://www.cplusplus.com/reference/clibrary/cstring/strcat/
the first parameter to strcat, must be big enough to hold the resulting string
try:
//assuming a,b are char*
char* sum = new char[strlen(a) +strlen(b)+1];
strcpy(sum,a);
strcat(sum,b);
There should be enough legal memory to hold the entire string.
char *one = new char[128]; //allocating enough memory!
const char *two = "two"; //"two" is const char*
strcpy(one, "one");
strcat(one, two); //now the variable "one" has enough memory to hold the entire string
By the way, if you prefer using std::string over char* in C++, such thing would be easier to handle:
#include<string>
std::string one = "one";
std::string two = "two";
one = one + two; //Concatenate
std::cout << one;
Output:
onetwo
There are two reasons for this.
If you have a pointer initialized to a string literal, that memory is read-only and modifying it will result in undefined behavior. In this case, if you try to append a string to a string literal, you'll be modifying this sort of memory, which will result in problems.
When using strcat you need to guarantee that space exists for the concatenation of the string at the location you're specifying. In this case, you cannot guarantee that, since a string literal is only guaranteed to have enough space to hold the literal itself.
To fix this, you'll want to explicitly allocate a buffer large enough to hold the concatenation of the two strings, including the null terminator. Here's one approach:
char* buffer = malloc(strlen(one) + strlen(two) + 1);
strcpy(buffer, one);
strcat(buffer, two);
Hope this helps!
The seg fault is because you attempt to write to read only memory. The first action of the strcat is to copy of 't' from the first entry of two into the null at the end of "one". So strictly the seg fault is not due to lack of storage - we never get that far. In fact this code will also likely give you a seg fault:
char* one = "one";
char* two = "";
strcat(one, two);
All this tries to do is copy a null over a null, but in read-only memory. I suppose a optimiser might happen to stop this on some platforms.
Oddly enough the following (incorrect) code will (probably) not give you a seg fault, and even give the "right" answer:
char one[] = "one";
char two[] = "two";
strcat(one, two);
printf("%s\n", one);
This successfully writes "onetwo" to stdout on my machine. We get a stack scribble, which we happen to get away with.
On the other hand this does seg fault:
char* one = "one "; // Plenty of storage, but not writable.
char two[] = "two";
strcat(one,two);
Hence the solution:
const unsigned enoughSpace = 32;
char one[enoughSpace] = "one";
char two[] = "two";
strcat(one,two);
printf("%s\n", one);
The issue with this is of course, how large to make enoughSpace in order to store what ever is coming?
Hence the functions strncat, or strcat_s, or more easily std::string.
Moral of the story: in C++, just like C, you really need to know what your memory layout is.
There are several problems here. Firstly, though you have casted the strings to mutable versions, they really are string literals and hence should not be written. Secondly, you are using strcat which will write into the string buffer, completely ignoring the length of the string buffer (it's better to use strncat which requires you to specify the length of the buffer). Lastly, since this is C++, it would be way better to use:
#include <string>
// ...
string one = "one";
string two = "two";
one.append(two);
You never reserved some space for your strings.
#include <string.h>
#include <stdio.h>
int main(void){
char str[20] = "";
strcat(str, "one");
strcat(str, "two");
printf("%s", str);
}
Would be one correct way to do this. The other (and way better) is to use the std::string class.
#include <string>
#include <cstdio>
int main(void){
std::string str;
str += "one";
str += "two";
std::printf("%s", str.c_str());
}
Your destination string should be large enough to hold both the destination and the source string. So an example would be
char one[10] = "one";
char two[4] = "two";
strcat(one,two);
strcat needs a "writeable" buffer as the target. In your example, it is a pointer to a string constant (or literal), which you cannot write to, thus it results in an exception. The target buffer can be a buffer on the stack or one dynamically allocated (e.g., with malloc).
This is not the problem of "not enough space".
char *a = "str";
Look at the code above, the pointer a is point to "static memory". The string "str" is stored in the static place in the PCB, which means it can't be overwritten.
So, the codes below will be better:
#include <string>
using std::string;
string a = "stra";
string b = "strb";
a += b;
How to assign a string to a char* (char pointer) in C++?
char *pw = some string
For constant initialization you can simply use
const char *pw = "mypassword";
if the string is stored in a variable, and you need to make a copy of the string then you can use strcpy() function
char *pw = new char(strlen(myvariable) + 1);
strcpy(pw, myvariable);
// use of pw
delete [] pw; // do not forget to free allocated memory
If you just want to assign a string literal to pw, you can do it like char *pw = "Hello world";.
If you have a C++ std::string object, the value of which you want to assign to pw, you can do it like char *pw = some_string.c_str(). However, the value that pw points to will only be valid for the life time of some_string.
If you mean a std::string, you can get a pointer to a C-style string from it, by calling c_str. But the pointer needs to be const.
const char *pw = astr.c_str();
If pw points to a buffer you've previously allocated, you might instead want to copy the contents of a string into that buffer:
astr.copy(pw, lengthOfBuffer);
If you're starting with a string literal, it's already a pointer:
const char *pw = "Hello, world".
Notice the const again - string literals should not be modified, as they are compiled into your program.
But you'll have a better time generally if you use std::string everywhere:
std::string astr("Hello, world");
By the way, you need to include the right header:
#include <string>
I think you may want to do this:
using namespace std;
string someString;
geline(cin,someString);
char *pw = strdup(someString.c_str());
But consider doing it another way. Check out http://tiswww.case.edu/php/chet/readline/rltop.html (GNU Readline library). I don't know details about it, just heard about it. Others may have more detailed or other tips for reading passwords from standard input.
If you only want to use it for a single call for something you do not need to copy the contents of someString, you may use someString.c_str() directly if it is required as const char *.
You have to use free on pw some time later,
String must be enclosed in double quotes like :
char *pStr = "stackoverflow";
It will store this string literal in the read only memory of the program.
And later on modification to it may cause UB.