I'm writing a exception class with a what() method.
const char* what() const throw() {
return "test";
}
works fine, but
const char* what() const throw() {
return (std::string("test")).c_str();
}
seems to return a random result. Why?
std::string("test") creates a temporary string object. c_str returns a pointer to some internal storage of that temporary object. After the function exits, that’s a dangling pointer – it points to invalid memory.
There is no way to circumvent this. You either have to make your string object more long-lived by declaring (and initialising, since the function is const) it outside the function – or you need to manually allocate heap storage inside the function, copy the string there, and return a pointer to that storage. However, this is complicated, error-prone, and violates the contract of the function, because the user of your error class doesn’t expect to free memory.
In fact, here’s a simple implementation of an error class (toy, since I don’t know your use-case) with this in mind:
struct my_logic_error : std::logic_error {
// `std::logic_error` already overrides `what`, we only need to initialise it!
my_logic_error(int errcode) :
std::logic_error{std::string{"Logic error occurred with error code "} +
std::to_string(errcode)} {}
};
Assuming you derive from an exception class without this luxury, your code gets minimally more complex:
struct my_error : std::exception {
my_error(int errcode) :
message{std::string{"Logic error occurred with error code "} +
std::to_string(errcode)} {}
char const* what() const noexcept {
return message.c_str();
}
private:
std::string message;
};
You store the string value in a member of your exception class, and you return c_str() on this member.
Doing a strdup can work, but the caller must free the memory, that's not a safe way of doing.
Related
I came from c++98, and i am trying to make my way in to c++11 and so on. i came across the public member function , std::exception::what, <=> virtual const char* what() const noexcept;
from this example givin in c++ reference : what_example, i can understand the usage but i have a few questions:
// exception::what
#include <iostream> // std::cout
#include <exception> // std::exception
struct ooops : std::exception {
const char* what() const noexcept {return "Ooops!\n";}
};
int main () {
try {
throw ooops();
} catch (std::exception& ex) {
std::cout << ex.what();
}
return 0;
}
in c++98 the what() was : virtual const char* what() const throw();, and in c++11, it becomes virtual const char* what() const noexcept;. what is the noexcept at the end? did it bring something new?
why should i use what() it at all? i can emplement my own tostring method in my class exception and call it instead!
in the return value of what(), see below, guaranteed to be valid at least until...or until a non-const member function of the exception object is called. what is the meaning of or until a non-const member function of the exception object is called, could some one explain with example and why is that ?
what() return value
A pointer to a c-string with content related to the exception. This is
guaranteed to be valid at least until the exception object from which
it is obtained is destroyed or until a non-const member function of
the exception object is called.
thanks.
what is the noexcept at the end?
It is a new specifier introduced in C++11. In very short, it means that the function will not throw an exception. noexcept has same meaning as throw().
did it bring something new?
noexcept is an improvement over the old throw specifier, which has since been deprecated (C++11) and then removed (C++20) from the language. It accepts a boolean expression that determines whether the function is noexcept or potentially throwing. This is useful in generic template programming because some instances of a template may be potentially throwing while others might not be.
why should i use what() it at all? i can emplement my own tostring method in my class exception and call it instead!
Because you may be using functions that are not written by you, and therefore will not throw your exception class. For example, some standard functions will in some cases throw an exception, and all standard exceptions derive from std::exception. In such case, the only way to access the error message is through the what member function.
Same applies when other people call your function. They might not want to / or need to know about your special exception class, but they can still catch it and print the message if you inherit std::exception.
what is the meaning of or until a non-const member function of the exception object is called
The meaning is literal. If you call what on an exception object derived from std::exception, and store the returned pointer, and then call a non-const member function of that exception object then the stored pointer will be invalid.
Any attempt to indirect through an invalid pointer such as attempting to print the exception message will result in undefined behaviour.
For your first question check out StoryTeller's comment. As for the second point:
why should i use what() it at all? i can emplement my
own tostring method in my class exception and call it instead!
The first rule of programming is do not reinvent the wheel, if there is a toString function or another function in the STL library that meets your needs, use it. Do not invent your own and try to debug it.
As an addition to the third question:
Sometimes, one happens to be surprised how important it can be that the wheel is not reinvented; and sharing the same basic class can be a big deal.
Thus, there comes a std::cerr message showing the contents of what, when the program crashes because of a thrown exception.
I have a C-Libraray function returning a C-String
const char* myFuncC(struct myS *);
Now I write a class mapper:
class myC {
private:
struct myS * hdl
...
public:
const char* myFunc() {
return myFuncC(hdl);
}
// want to have...
const std::string& myFuncS() {
return ??? myFuncC(hdl);
}
}
Now I would like to return a: const std::string& and I don't want to copy the C-String pointer data
How I do this?
update
Is there a C++ Class who act like a const C++-String class and using a const C-String pointer as string source ?
I would call this class a C++-String-External … External mean … using a external source as storage… in my case a "const char *"
std::string, by definition, owns its memory and there’s nothing we can do to change this. Furthermore, by returning a reference you’re creating a dangling reference to a local variable (or a memory leak).
However, the idea of encapsulating contiguous character ranges in a string-like interface without copying is such a common problem that C++17 added a new type, std::string_view, to accomplish exactly that. With it, your code can be written as:
std::string_view myFuncS() {
return {myFuncC(hdl)};
}
A string_view isn’t a string but it has a very similar API and the idea is to use it instead of many current uses of string const&. It’s perfect for the job here.
Note that we are returning a copy, to avoid a dangling reference. However, this does not copy the underlying memory, and is cheap — almost as cheap as returning the reference.
Simply return a new string:
std::string myFuncS() {
return std::string(myFuncC(hdl));
}
If you really need a refence or a pointer then allocate the string on the heap and return a pointer to it:
std::unique_ptr<std::string> myFuncS() {
return std::unique_ptr<std::string>(new std::string(myFuncC(hdl)));
}
I have a rapidjson wrapper that does the following:
class ADocument
{
void setJson(const char *data) { m_D.parse(data); }
AData operator[](const char *key) const
{
const rapidjson::Value *value = rapidjson::Pointer(key).Get(m_D);
if(value)
return AData(value);
else
return AData(&m_D);
}
private:
rapidjson::Document m_D;
};
and the AData class like this:
class AData
{
public:
Adata(const rapidjson::Value *val) : m_Value(val) {}
operator QString() const { return m_Value.IsString() ? m_Value.GetString() : QString(); }
private:
const rapidjson::Value *m_Value;
};
And the whole thing is called like this:
ADocument doc;
doc.setJson("{\"Hello\":{\"Hello\":\"test\"}}");
QString str = doc["/Hello/Hello"];
when str becomes "test".
Now by debugging this code I found out that the AData object somehow shifts - the operator QString() gets called from an object in different memory location than the original AData object is constructed in the operator[] of ADocument. Regular constructor is called once. But it might be that copy-elision simply moved the same object around in memory.
However when I define one of rule-of-three/five methods such as a destructor in AData without changing anything else (and the destructor does nothing itself) then the operator QString() is called on the SAME OBJECT (same memory location) which got constructed in the operator[] of ADocument.
Even when I implemented all thinkable constructors and operators (move, copy, assign...) NONE of them is ever called but the result is the same - only one object is ever created.
What is going on here? I would like to understand it.
And further, how to change this implementation so that it is as performance and memory efficient as possible (=minimum copies etc.)? Or maybe I am really worrying about nothing here and what I am seeing is only some compiler optimization?
What is going on here? I would like to understand it.
You're experiencing copy elision.
When a unnamed temporary would be copied or moved into a variable of the same type, the compiler is allowed to construct the object directly in the variable and skip the copy or move operation.
Another situation where you may experience this is when you return a variable with automatic storage duration from a function.
i could not find threads giving a clear answer on this -
i have a constructor, for example:
FanBookPost::FanBookPost(Fan* owner, std::string content);
Fan is another class in my code, but content is the problematic one:
since std::string is not a pointer, i would expect that calling the constructor with (fan, nullptr) would not be possible. however, it compiles! ... and crashes at runtime with EXC_BAD_ACCESS.
is this avoidable?
The problem here is that the crash will occure when the constructor of std::string is called (as a nullptr interpreted as const char* is accessed there). There is nothing here you can do against this but to tell other peoples not to do shit. Its not a problem of your constructor and thus not your responsibility (besides that you cant prevent it).
What you're observing is that you can implicitly create a std::string from a character pointer (nullptr in this case) which is then passed to the function. However creating a string from a null pointer is not allowed. There is nothing wrong with your method signature, just the client use that violates the std::string constructor's contract.
How about using a proxy / wrapper typ, if you really want to be safe:
template<typename T>
struct e_t
{
public:
inline e_t ( e_t const & other )
: m_value( other.m_value )
{}
inline T & value( void ) { return m_value; }
inline operator T&() { return m_value; }
inline e_t( const T& c ) : m_value( c ) {}
private:
T m_value;
};
void FanBookPost(int* owner, e_t<std::string> content) {
}
int main()
{
int n = 0;
//FanBookPost(&n, 0); // compiler error
//FanBookPost(&n, nullptr); // compiler error
//FanBookPost(&n, ""); // unfortunately compiler error too
FanBookPost(&n, std::string(""));
}
The problem is that std::string has a non-explicit ctor that takes a char * as its sole (required) parameter. This gives an implicit conversion from nullptr to std::string, but gives undefined behavior, because that ctor specifically requires a non-null pointer.
There are a few ways to prevent this. Probably the most effective would be to take a (non-const) reference to a std::string, which will require passing a (non-temporary) string as the parameter.
FanBookPost::FanBookPost(Fan* owner, std::string &content);
This does have to unfortunate side effect of giving the function the ability to modify the string that's passed. It also means that (with a conforming compiler1) you won't be able to pass nullptr or a string literal to the function--you'll have to pass an actual instance of std::string.
If you want to be able to pass a string literal, you can then add an overload that takes a char const * parameter, and possibly one that takes a nullptr_t parameter as well. The former would check for a non-null pointer before creating a string and calling the function that takes a reference to a string, and the latter would do something like log the error and unconditionally kill the program (or, just possibly, log the error and throw an exception).
That's annoying and inconvenient, but may be superior to the current situation.
Unfortunately, the last time I noticed MS VC++ did not conform in this respect. It allows passing a temporary object by non-const reference. Normally that's fairly harmless (it just lets you modify the temporary, but that normally has no visible side effects). In this case it's much more troublesome though, since you're depending on it specifically to prevent passing a temporary object.
I am new here.
I am also new on C++
So here is the class and function i wrote.But i got the compiler error
My class:
class fooPlayer
{
public:
void fooPlayerfunc(){}//doing something here
char askYesNo(std::string question);
};
class fooPlayerFactory
{
public:
virtual std::auto_ptr<fooPlayer> MakePlayerX() const;
virtual std::auto_ptr<fooPlayer> MakePlayerO() const;
private:
std::auto_ptr<fooPlayer> MakePlayer(char letter) const;
std::auto_ptr<fooPlayer> my_player;
};
Implement my class:
auto_ptr<fooPlayer> fooPlayerFactory:: MakePlayer(char letter) const
{
my_player->fooPlayerfunc();
return my_player;
}
auto_ptr<fooPlayer> fooPlayerFactory::MakePlayerX() const
{
char go_first = my_player->askYesNo("Do you require the first move?");
MakePlayer(go_first);
return my_player;
}
auto_ptr<fooPlayer> fooPlayerFactory::MakePlayerO() const
{
return my_player;
}
My main() function here:
int main()
{
fooPlayerFactory factory;
factory.MakePlayerX();
factory.MakePlayerO();
}
I got the error:
error C2558: class 'std::auto_ptr<_Ty>' : no copy constructor available or copy constructor is declared 'explicit'
I do not know how to change it even after reading the document on this link:
The reason for the error is that you are calling the copy constructor of auto_ptr my_player in fooPlayerFactory::MakePlayerO() which is a const method. That means that is cannot modify its members.
However the copy constructor of auto_ptr DOES modify the right hand side so returning my_player trys to change its pointer to 0 (NULL), while assigning the original pointer to the auto_ptr in the return value.
The signature of the copy constuctor is
auto_ptr<T>::auto_ptr<T>(auto_ptr<T> & rhs)
not
auto_ptr<T>::auto_ptr<T>(const auto_ptr<T> & rhs)
The copy constructor of auto_ptr assigns ownership of the pointer to the left hand side, the right hand side then holds nothing.
I don't think you want to use auto_ptr here, you probably want boost::smart_ptr
It looks like you have mixed up two uses for auto_ptr
The first is as poor man's boost::scoped_ptr. This is to manage a single instance of a pointer in a class, the class manages the life time of the pointer. In this case you don't normally return this pointer outside your class (you can it is legal, but boost::smart_ptr / boost::weak_ptr would be better so clients can participate the life time of the pointer)
The second is its main purpose which is to return a newly created pointer to the caller of a function in an exception safe way.
eg
auto_ptr<T> foo() {
return new T;
}
void bar() {
auto_ptr<T> t = foo();
}
As I said I think you have mixed these two uses auto_ptr is a subtle beast you should read the auto_ptr docs carefully. It is also covered very well in Effective STL by Scott Meyers.
In your code:
auto_ptr<fooPlayer> fooPlayerFactory:: MakePlayer(char letter) const
{
my_player->fooPlayerfunc();
return my_player;
}
This is a const function, but fooPlayerfunc is not const - my compiler reports this error rather than the one you say you are getting. Are you posting the real code?
I don't think you actually want to constructing dynamic objects here.
A factory object creates and returns an object it normally does not keep a reference to it after creation (unless you are sharing it), and I don't actually see anywhere that you are creating the player.
If you only ever create one player internally in your (fooPlayerFactory). Then create an object and return references to it.
Edit: in response to the comment (which is correct, my bad), I left only the advice part.
Best practice is to have the factory methods just return a plain old pointer to the underlying object, and let the caller decide how to manage ownership (auto_ptr, scoped_ptr, or whatever).
Also your code is buggy, any class that implements virtual methods should have a virtual destructor.
I'm not seeing anywhere you construct my_player, so I have a feeling that some of the code is missing. Specifically, I think your constructor has this line:
my_player = new fooPlayer()
A fooPlayer object is not quite the same thing as an auto_ptr<fooPlayer> object, and auto_ptr is intentionally designed to prevent assigning from one to the other because, frankly, the alternative is worse. For the details, look up (1) conversion constructors, (2) the explicit keyword, and (3) copy constructors and destructive copy semantics.
You should change the constructor to either:
class fooPlayerFactory {
public:
fooPlayerFactory()
{
my_player = std::auto_ptr<fooPlayer>(new fooPlayer());
}
Or (using a member initializer list):
class fooPlayerFactory {
public:
fooPlayerFactory() : my_player(std::auto_ptr<fooPlayer>(new fooPlayer()) { }
The solution isn't pretty but, like I said, the alternative is worse due to some really arcane details.
As a bit of advice, though, you're making life harder than it needs to be; and may in fact be causing strange bugs. auto_ptr exists to manage the lifetime of an object, but the only reason you need to worry about the lifetime of my_player is that you've allocated it with new. But there's no need to call new, and in fact there's no need to keep my_player. And unless fooPlayerFactory is meant to be the base class for some other factory, there's no need to mark functions virtual.
Originally I thought you could get away with simply returning copies of the my_player object, but there's a problem: before returning my_player from MakePlayer() you call a method on it, and I assume that method changes the internal state of my_player. Further calls to MakePlayer() will change the state again, and I think you're going to eventually have my_player in the wrong state. Instead, return a different fooPlayer object with each request. Don't do memory management, just promise to construct the object. That way the user can decide on memory allocation:
fooPlayerFaclotry factory;
fooPlayer on_stack = factory.MakePlayerX();
fooPlayer* on_heap_raw_pointer = new fooPlayer(factory.MakePlayerO());
std::auto_ptr<fooPlayer> on_heap_managed_scope
= std::auto_ptr<fooPlayer>(factory.MakePlayerX());
I would change fooPlayerFactory to look like this:
class fooPlayerFactory
{
private:
fooPlayer MakePlayer(const char letter) const
{
fooPlayer result;
result.fooPlayerfunc();
return result;
}
public:
fooPlayer* MakePlayerX() const
{
char go_first = askYesNo("Do you require the first move?");
return MakePlayer(go_first);
}
fooPlayer MakePlayerO() const
{
return fooPlayer();
}
};