Consider a custom error type written using the LLVM system_category
implementation for reference:
#include <iostream>
#include <system_error>
struct my_error_category_type : std::error_category {
char const* name() const noexcept override { return "name"; }
std::string message(int i) const noexcept override{ return "message"; }
~my_error_category_type() {
std::cout << "Destroyed the category" << std::endl;
}
};
std::error_category const& my_error_category() noexcept {
static my_error_category_type c;
return c;
}
Now imagine the following simple class that uses std::error_code
to handle errors:
std::error_code do_some_setup() {
return std::error_code(1, my_error_category());
}
std::error_code do_some_cleanup() {
return std::error_code(2, my_error_category());
}
struct MyObj {
void method() {
// this constructs the category for the first time
auto err = do_some_setup();
std::cout << err << std::endl;
}
~MyObj() {
std::cout << "Running cleanup" << std::endl;
auto err = do_some_cleanup();
std::cout << err << std::endl;
}
};
The following code gives alarming output
static MyObj obj;
int main() {
obj.method(); // remove this line, and the output is fine
}
name:1
Destroyed the category
Running cleanup
name:2
Note how my_error_category_type::message
was called on a destructed object!
My questions are:
- Is calling
message
on this destructed object safe? - If not, is there a way to preserve the lifetime of the category? Can I make the object immortal somehow?
- Does the standard make any guarantees about the lifetime of the builtin
std::system_category()
objects and the like? The LLVM implementation I link to above suffers exactly the same problem.
Aucun commentaire:
Enregistrer un commentaire