I have some existing code in a header file which needs to be useable in the context of C++03 & C++11
It defines a macro TABORT
that takes in a printf
-style format string & arguments to be formatted using that string, prints the result to stdout
, and then calls std::abort
Essentially, something similar to
#define TABORT(...) do { fprintf(stderr, "Aborting at %s:%d for reason: ", __FILE__, __LINE__); fprintf(stderr, __VA_ARGS__); std::abort(); } while(0)
I wanted to add some logic to catch the case where evaluating __VA_ARGS__
would throw an exception, preventing the call to std::abort
. For example, in the following:
if (SomethingReallyBadHappened())
TABORT("Aborting because %s", GetReallyBadDetails().c_str());
if GetReallyBadDetails
throws an exception, I want to ensure that abort gets called (here, not after some exception unwinding).
So, I did something like:
#define TABORT(...) do { fprintf(stderr, "Aborting at %s:%d for reason: ", __FILE__, __LINE__); try { fprintf(stderr, __VA_ARGS__); } catch (...) { fprintf(stderr, "<Failed to evaluate abort message>\n"); } std::abort(); } while(0)
But this is causing the C4714 warning in visual studio when the macro is used in functions marked __forceinline
, probably due to
In some cases, the compiler will not inline a particular function for mechanical reasons. For example, the compiler will not inline:
- A function with a try (C++ exception handling) statement.
So, to avoid that warning (& to keep inlining functions which were previously determined to need inlining inlined [I hope this was done alongside profiling...]), I was thinking to do something like
// In header
// Assume this is like std::function except construction from a lambda can't throw
template <typename Sig>
class function_ref;
using PrintAbortMsg = function_ref<void(const char*)>;
void [[noreturn]] do_tabort(const char* file, int line, function_ref<void(PrintAbortMsg &)> msgGenerator) noexcept;
#define TABORT(...) do_tabort(__FILE__, __LINE__, [&](PrintAbortMsg& print) { print(SprintfToStdString(__VA_ARGS__).c_str()); })
// In cpp
void do_tabort(const char* file, int line, function_ref<void(PrintAbortMsg&)> msgGenerator) noexcept
{
fprintf(stderr, "Aborting at %s:%d for reason: ", __FILE__, __LINE__);
try
{
msgGenerator([](const char* msg) { fprintf(stderr, "%s\n", msg); });
}
catch (...)
{
fprintf(stderr, "<Failed to evaluate abort message>\n");
}
std::abort();
}
Which I think would work in the context of C++11, but I'm not sure how to do something which will work for for C++03. There are existing usages of the macro which I don't want to touch.
Aucun commentaire:
Enregistrer un commentaire