I have this function, where I'm trying to return a const char*, but when I try to output the returned value, I get garbage value;
virtual const char* what() const noexcept
{
std::stringstream s;
if(m_id > -1)
s << m_message << " with id " << m_id << " does not exist";
else
s << m_message << " with name " << m_name << " does not exist";
//until now it works fine
std::string tmp = s.str();
const char* temp = tmp.c_str();
return temp; //after I execute this command, the value is deleted.
}
when I try to print:
catch (std::exception& e)
{
std::cout << e.what() << std::endl;
}
I get this (different every time..) :
▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌╢Pⁿש▌'
What am I doing wrong?
You are returning a pointer to the internal char data of a local std::string object that is destroyed when the function exits, thus the returned pointer is left dangling, pointing at invalid memory. Trying to access the data afterwards is undefined behavior.
Normally, you would have two choices to fix that:
return a std::string instead of a char* pointer.
allocate the char data dynamically, and then make the caller free it when done using it.
However, in this case, you are overriding the std::exception::what() method, so neither of those options are viable. What you will have to do instead is store your char data in a std::string member of your derived class, and then you can return a char* pointer to its data, eg:
private:
std::string m_what;
myException::myException(...)
{
...
std::stringstream s;
if (m_id > -1)
s << m_message << " with id " << m_id << " does not exist";
else
s << m_message << " with name " << m_name << " does not exist";
m_what = s.str();
}
virtual const char* what() const noexcept
{
return m_what.c_str();
}
If you derive your exception class from std::runtime_error instead of std::exception directly, this is already handled for you. std::runtime_error takes a string in its constructor, and overrides what() to return that string's data.
The problem is that tmp is local to the function what and you're returning a pointer to that local's internal array. This is a problem because the local will be destroyed once the function exits. That is, the pointer that you return is a dangling pointer. Using that dangling pointer(which you do when you wrote std::cout << e.what() << std::endl;) is undefined behavior.
Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior.
So the output that you're seeing(maybe seeing) is a result of undefined behavior. And as i said don't rely on the output of a program that has UB. The program may just crash.
So the first step to make the program correct would be to remove UB. Then and only then you can start reasoning about the output of the program.
1For a more technically accurate definition of undefined behavior see this where it is mentioned that: there are no restrictions on the behavior of the program.
Related
try {
char message = "Error!";
throw message;
}
Catch site.
catch (char* &e) {
court << e << endl;
return 0;
}
Does anyone know how to fix this?
I want to display an error message but am required to do so with a C-string.
You are not throwing the string or the array. Because of array-to-pointer decay you are throwing a pointer to the first element of the message array. You are catching that pointer just fine. Unfortunately during stack unwinding the array into which the pointer is pointing is destroyed since it is a local variable in the if block and your catch block is outside that if block. So you are then trying to dereference a dangling pointer in cout << *e << endl;, causing undefined behavior.
In theory you can do
const char* message = "Error! Invalid data for: Total Crew.";
throw message;
or
throw "Error! Invalid data for: Total Crew.";
to throw pointers to the string literals, which live until the end of the program, but that is really bad practice. You should instead write a class inherited from std::exception or another standard library exception class like std::invalid_argument and then throw an instance of your exception class. This way you can make catch clauses to handle specific types of exceptions, not just generic char* that could mean anything.
Also cout << *e << endl; would print only the first character of the string, even if there wasn't the lifetime issue. You probably meant cout << e << endl; instead.
but am required to do so with a C-string.
There is no good reason for that, except as far as all string literals are C-style strings. The exception classes inherited from std::exception allow one to provide a string argument to store in the exception object via the constructor and to retrieve it with the .what() member function in the catch handler.
You could even use them directly, without inheriting your own exception class:
if (totalCrew <=0) {
throw std::invalid_argument("Error! Invalid data for: Total Crew.");
}
//...
catch (const std::invalid_argument& e) {
cout << e.what() << endl;
cout << "Line: " << line << endl;
return 0;
}
# include <iostream>
# include <string>
using std::string;
using std::cout;
using std::endl;
string func() {
string abc = "some string";
return abc;
}
void func1(string s) {
cout << "I got this: " << s << endl;
}
int main() {
func1(func());
}
This gives:
$ ./a.out
I got this: some string
How/why does this code work ? I wonder because abc went out of scope and got destroyed as soon as the call to func() completed. So a copy of abc cannot be/should not be available in variable s in function func1 Is this understanding correct ?
The return value is copied from the local variable, effectively creating a new string object.
However, RVO (returned value optimization) should eliminate this step.
Try single stepping your code in a debugger. You should see the std::string copy constructor called for the return line. Be sure to compile with debug enabled and optimizers off.
Your code is essentially asking:
"Call func1, and in order for func1 to work I have to receive a string which we can use by calling the copy constructor on that string. The parameter for func1 we want to come from the return value of func (which we know has to be a string since its explicitly defined".
abc goes out of scope only after the copy constructor is called on the return value of func() which passes the value of the string. In theory you could have written it passed by reference or constant reference:
void func1(string& s) {
cout << "I got this: " << s << endl;
}
Which allows func1 to directly access the string in memory through a pointer (and also change it, if your code was meant to.)
void func1(string const& s) {
cout << "I got this: " << s << endl;
}
Which provides a constant reference to the string from func(). This ensures that you get a pointer to the data and that you won't change its contents. Typically passing data by constant reference (const&) is desirable because it's very fast and keeps your code from accidentally changing data that it shouldn't.
You really only need to pass by value if you're going to manipulate the data once you pass it to the new function, saving you the resources of creating another new container to handle the manipulation:
void func1(string s) {
s += " some extra stuff to add to the end of the string"; //append some new data
cout << "I got this: " << s << endl;
}
While testing the examples trough the boost cpp libraries book I noticed that changing the type stored inside a boost::any variable may lead to an illegal access instead of an exception:
good:
boost::any a = 1;
bool *p = boost::any_cast<bool>(&a); // ok, bad cast exception
bad:
boost::any a = std::string { "Boost" };
a = 1;
bool *p = boost::any_cast<bool>(&a); // no exception thrown
std::cout << std::boolalpha << *p << '\n'; // illegal access
My question therefore is: is this a bug as it seems or is it some underlying fact related to templates usage that I am not aware of?
I understand the documentation differently:
Returns: If passed a pointer, it returns a similarly qualified pointer to the value content if successful, otherwise null is returned. If T is ValueType, it returns a copy of the held value, otherwise, if T is a reference to (possibly const qualified) ValueType, it returns a reference to the held value.
Throws: Overloads taking an any pointer do not throw; overloads taking an any value or reference throws bad_any_cast if unsuccessful.
So:
The success or failure of the conversion depends on the stored type and target type.
The manifestation of failure though, depends on whether you pass a pointer to any_cast or not. If you pass a pointer, the manifestation is a nullptr; otherwise, the manifestation is an exception.
Consider for example this code:
#include <boost/any.hpp>
#include <iostream>
int main() {
boost::any a = 1;
This seems to contradict the statement in your question - since it takes a pointer, it doesn't throw, but the pointer is nullptr:
bool *p = boost::any_cast<bool>(&a);
// Prints true
std::cout << std::boolalpha << (p == nullptr) << std::endl;
This is how it looks when it's OK:
int *q = boost::any_cast<int>(&a);
// Prints false
std::cout << std::boolalpha << (q == nullptr) << std::endl;
This throws, because it doesn't take a pointer:
try {
boost::any_cast<bool>(a);
}
catch(...) {
std::cout << "caught" << std::endl;
}
Same for a string stored type:
a = std::string { "Boost" };
p = boost::any_cast<bool>(&a);
// Prints true
std::cout << std::boolalpha << (p == nullptr) << std::endl;
try {
boost::any_cast<bool>(a);
}
catch(...) {
std::cout << "caught again" << std::endl;
}
}
I am trying to store a char* into a struct's char* field. I have tried different things but none of them worked. The problematic piece of code is shown below:
pInfo is the object of the struct PlayerInfo.
PlayerInfo *pInfo = (PlayerInfo*)malloc(sizeof(PlayerInfo));
The char* I get from GetAddress is stored in the Address field of PlayerInfo.
pInfo->Address = GetAddress(pInfo->playerId);
The GetAddress function is shown below. It converts integers to strings, stores them in a vector and returns the vector as a char* using &retChar[0].
char* GetAddress(int playerId)
{
std::string strPlayerId = std::to_string(playerId);
std::string strGroupId = std::to_string(group.GetGroupId());
std::string retAddress = strPlayerId + ":" + strGroupId + ":" + GenRandomChar();
//From -- http://stackoverflow.com/questions/347949/convert-stdstring-to-const-char-or-char
std::vector<char> retChar(retAddress.begin(), retAddress.end());
retChar.push_back('\0');
for(std::vector<char>::const_iterator i = retChar.begin(); i != retChar.end(); ++i)
std::cout << "retChar is " << *i << std::endl;
return &retChar[0];
}
When I print the contents, only garbage is printed. I tried printing the memory contents from gdb, but that also did not help.
char* address = GetAddress(pInfo->playerId);
std::cout << "address is " << *address << std::endl;
std::cout << "address is " << pInfo->Address << std::endl;
std::cout << "address is " << *(pInfo->Address) << std::endl;
The problem is, that your function scope local variable
std::vector<char> retChar;
goes out of scope and is destroyed after your function returned.
Thus using the returned pointer return &retChar[0]; is calling undefined behavior.
The better choice would be to pass the pointer where to copy the data as a reference
void GetAddress(int playerId, char*& result) {
std::vector<char> retChar;
// ...
std::copy(retChar.begin(),result);
}
and ensure result buffer is big enough to receive the copied data.
NOTE:
The above suggestion just solves the 1st level of your current problem. The probably better idea is to change your function simply to deal with std::string instead of using std::vector<char> and raw char* pointers (if your use case allows to refactor this):
Make PlayerInfo::Address member a std::string type
struct PlayerInfo {
// ...
std::string Address;
};
and define your GetAddress() function as follows
std::string GetAddress(int playerId) {
std::ostringstream result;
result << playerId << ":" group.GetGroupId() << ":" << GenRandomChar();
return result.str();
}
and use the results std::string::c_str() method if you really need a const char* value to pass it elsewhere.
I think the idea of using std::vector<char> in the selected answer to How to convert a std::string to const char* or char*? is that the std::vector<char> is your writable character array, not that you should extract a char * from it. (You can, however, copy the contents into a different memory location identified by a char *, as you have already seen.)
But I would ask why you are storing a char * in the Address member of PlayerInfo. Why don't you make that member an std::string and change the return type of getAddress() to std::string, in which case getAddress can simply return retAddress?
Alternatively, you can declare getAddress like this: void getAddress(int playerId, std::string& retAddress) and the code inside the function is even simpler, because you don't have to declare retAddress as a local variable inside the function.
In C++ what is the best way to return a function local std::string variable from the function?
std::string MyFunc()
{
std::string mystring("test");
return mystring;
}
std::string ret = MyFunc(); // ret has no value because mystring has already gone out of scope...???
No. That is not true. Even if mystring has gone out of scope and is destroyed, ret has a copy of mystring as the function MyFunc returns by value.
There will be a problem if your code is like:
std::string& MyFunc()
{
std::string mystring("test");
return mystring;
}
So, the way you've written it is OK. Just one advice - if you can construct the string like this, I mean - you can do it in one row, it's sometimes better to do it like this:
std::string MyFunc()
{
return "test";
}
Or if it's more "complicated", for example:
std::string MyFunct( const std::string& s1,
const std::string& s2,
const char* szOtherString )
{
return std::string( "test1" ) + s1 + std::string( szOtherString ) + s2;
}
This will give a hint to your compiler to do more optimization, so it could do one less copy of your string (RVO).
None of the previous answers contained the key notion here. That notion is move semantics. The std::string class has the move constructor, which means it has move semantics. Move semantics imply that the object is not copied to a different location on function return, thus, providing faster function execution time.
Try to step debug into a function that returns std::string and examine the innards of that object that is about to be return. You shall see a member field pointer address xxx. And then, examine the std::string variable that received the function's return value. You shall see the same pointer address xxx in that object.
This means, no copying has occurred, ladies and gentlemen. This is the move semantics, God bless America!
As mentioned, the std::string is copied. So even the original local variable has gone out of scope, the caller gets a copy of the std::string.
I think reading on RVO can totally clear your confusion. In this case, it's accurately referred to as NRVO (Named RVO) but the spirit is the same.
Bonus reading: The problem with using RVO is that it's not the most flexible thing in the world. One of the big buzzes of C++0x is rvalue references which intends to solve that problem.
Have you tried it?
The string is copied when it's returned.
Well that's the official line, actually the copy is probably optimised away, but either way it's safe to use.
Well, ret will have a value of mystring after MyFunc(). In case of returning the result by value a temporary object is constructed by copying the local one.
As for me, there are some interesting details about the topic in these sections of C++ FAQ Lite.
It depends on the use case. If an instance should keep responsibility for a string, strings should be returned by a const reference. The problem is, what to do, if there isn't any object to return. With pointers, the invalid object could be signaled using 0. Such a "null-object" could be also used with references (e.g., NullString in the code snippet).
Of course, a better way to signal an invalid return value is throwing exceptions.
Another use case is if the responsibility for the string is transferred to the caller. In this case auto_ptr should be used. The code below shows all this use cases.
#include <string>
#include <memory> //auto_ptr
#include <iostream>
using std::string;
using std::auto_ptr;
using std::cout;
using std::endl;
static const string NullString("NullString\0");
///// Use-Case: GETTER //////////////////
//assume, string should be found in a list
// and returned by const reference
//Variant 1: Pseudo null object
const string & getString( bool exists ) {
//string found in list
if( exists ) {
static const string str("String from list");
return str;
}
//string is NOT found in list
return NullString;
}
//Variant 2: exception
const string & getStringEx( bool available ) {
//string found in list
if( available ) {
static const string str("String from list");
return str;
}
throw 0; //no valid value to return
}
///// Use-Case: CREATER /////////////////
auto_ptr<string> createString( bool ok )
{
if( ok ){
return auto_ptr<string>(new string("A piece of big text"));
}else{
return auto_ptr<string>();
}
}
int main(){
bool ok=true, fail=false;
string str;
str = getString( ok );
cout << str << ", IsNull:"<<( str == NullString )<<endl;
str = getString( fail );
cout << str << ", IsNull:"<<( str == NullString )<<endl;
try{
str = getStringEx( ok );
cout << str <<endl;
str = getStringEx( fail );
cout << str <<endl; //line won't be reached because of ex.
}
catch (...)
{
cout << "EX: no valid value to return available\n";
}
auto_ptr<string> ptext = createString( ok );
if ( ptext.get() ){
cout << *ptext << endl;
} else {
cout << " Error, no text available" << endl;
}
ptext = createString( fail );
if ( ptext.get() ){
cout << *ptext << endl;
} else {
cout << " Error, no text available"<<endl;
}
return 0;
}