23 #ifndef RC_NO_STACKTRACE
40 const size_t ErrorMsg_text_bufsize = 4096;
41 const size_t ErrorMsg_what_bufsize = 4096+1024;
60 class ErrorMsg :
virtual public std::exception {
61 size_t AmountWritten(
size_t size,
size_t written) {
62 return (size <= written) ? size-1 : written;
66 #define R_Safe_snprintf(str, size, ...) \
67 AmountWritten(size, size_t(snprintf(str, size, __VA_ARGS__)));
81 ErrorMsg(
const char* new_err_msg=NULL,
const char* filename=NULL,
84 char stacktrace_txt[ErrorMsg_text_bufsize] = {0};
87 if (new_err_msg == NULL) {
92 err_msg[ErrorMsg_text_bufsize-1] =
'\0';
95 #ifndef RC_NO_STACKTRACE
97 int backtrace_cnt = 0;
98 const int backtrace_size = 128;
99 void *bt_buffer[backtrace_size];
101 char **backtrace_symb;
102 backtrace_cnt = backtrace(bt_buffer, backtrace_size);
103 backtrace_symb = backtrace_symbols(bt_buffer, backtrace_cnt);
105 if (backtrace_symb != NULL) {
106 for (
int i=0; i<backtrace_cnt; i++) {
107 offset += R_Safe_snprintf(stacktrace_txt+offset,
109 backtrace_symb[backtrace_cnt-i-1]);
111 offset += R_Safe_snprintf(stacktrace_txt+offset,
114 SafeFree(backtrace_symb);
123 if (SymInitialize && SymFromAddr && SymCleanup) {
124 HANDLE process = GetCurrentProcess();
125 SymInitialize(process, NULL,
true);
128 const size_t symbolnamelen = 255;
129 char symboldata[
sizeof(SYMBOL_INFO)+(symbolnamelen+1)];
130 SYMBOL_INFO *symbol =
reinterpret_cast<SYMBOL_INFO*
>(symboldata);
131 symbol->MaxNameLen = symbolnamelen;
132 symbol->SizeOfStruct =
sizeof(SYMBOL_INFO);
134 backtrace_cnt = CaptureStackBackTrace(0, backtrace_size,
137 for(
int i=0; i<backtrace_cnt; i++) {
138 offset += R_Safe_snprintf(stacktrace_txt+offset,
140 static_cast<long unsigned int>(
size_t(bt_buffer[i])));
141 if (SymFromAddr(process, DWORD64(bt_buffer[i]), 0, symbol)) {
142 offset += R_Safe_snprintf(stacktrace_txt+offset,
144 static_cast<long unsigned int>(
size_t(symbol->Address)));
147 offset += R_Safe_snprintf(stacktrace_txt+offset,
151 offset += R_Safe_snprintf(stacktrace_txt+offset,
160 if (filename != NULL && filename[0] !=
'\0') {
161 written = snprintf(what_msg, ErrorMsg_what_bufsize,
162 "%s, %s, line %d%s", err_msg, filename, line_number,
166 written = snprintf(what_msg, ErrorMsg_what_bufsize,
"%s%s", err_msg,
169 if (written >=
int(ErrorMsg_what_bufsize)) {
170 for (
size_t i=ErrorMsg_what_bufsize-4; i<ErrorMsg_what_bufsize-1;
174 what_msg[ErrorMsg_what_bufsize-1] =
'\0';
178 #undef R_Safe_snprintf
204 return (0 == strncmp(err_msg, test_err, ErrorMsg_text_bufsize));
226 char err_msg[ErrorMsg_text_bufsize];
227 char what_msg[ErrorMsg_what_bufsize];
239 #define RC_MAKE_ERROR_TYPE(Type) \
240 class ErrorMsg##Type : virtual public RC::ErrorMsg {\
244 ErrorMsg##Type(const char* new_err_msg, const char* filename = "",\
245 int line_number = 0)\
246 : RC::ErrorMsg(new_err_msg, filename, line_number) {\
247 snprintf(type_msg, ErrorMsg_type_bufsize, #Type);\
274 #define Throw_RC_Error(err) throw RC::ErrorMsg(err, __FILE__, __LINE__)
282 #define Throw_RC_Type(Type, err) throw RC::ErrorMsg##Type(err, __FILE__, __LINE__)
286 #define Catch_RC_Error() catch (RC::ErrorMsgFatal& err) { fprintf(stderr, "Fatal Error: %s\n", err.what()); exit(-1); } catch (RC::ErrorMsg& err) { fprintf(stderr, "Error: %s\n", err.what()); }
289 #define Catch_RC_Error_Exit() catch (RC::ErrorMsg& err) { fprintf(stderr, "Error: %s\n", err.what()); exit(-1); }
315 memset (&sa, 0,
sizeof(sa));
317 sigaction(SIGSEGV, &sa, NULL);
#define Throw_RC_Type(Type, err)
Use this to throw an RC:ErrorMsg subtype exception.
Definition: Errors.h:282
#define RC_MAKE_ERROR_TYPE(Type)
Creates new RC::ErrorMsg subtypes.
Definition: Errors.h:239
#define RC_DYNAMIC_LOAD_FUNC_RAW(FuncName, Library)
Use as RC_DYNAMIC_LOAD_FUNC_RAW(FuncName,Library) to load FuncName from the dynamic library file Libr...
Definition: Macros.h:197
Ptr< Type > Cast()
Dynamically casts to an RC::Ptr of the type used as a template parameter on this function.
Definition: PtrCommon.h:57
The version information and configuration settings for RC Lib.
Provides typedefs and routines for working with primitives.
#define RC_NOEXCEPT
Provides noexcept if available.
Definition: Types.h:64
An exception class that records where the exception was thrown and provides a stack trace.
Definition: Errors.h:60
virtual const char * GetType() const noexcept
Provides the type of the exception if this is a subclass.
Definition: Errors.h:193
virtual const char * GetError() const noexcept
Provides the reason given for the error.
Definition: Errors.h:184
virtual bool IsError(const char *test_err) const noexcept
Return true if the the reason for the exception matches test_err.
Definition: Errors.h:203
ErrorMsg(const char *new_err_msg=NULL, const char *filename=NULL, int line_number=0) noexcept
The default constructor.
Definition: Errors.h:81
virtual const char * what() const noexcept
Returns a full descriptive error message with reason, source location, and stack trace.
Definition: Errors.h:213
A class with static methods for file and directory info and manipulation.
Definition: File.h:1214
Provides both client and server sides of blocking TCP connections.
Definition: Net.h:429
A static class for catching and throwing segfaults.
Definition: Errors.h:300
static void Handler(int)
The default handler for a segfault. It throws ErrorMsgFatal.
Definition: Errors.h:304
static void SetHandler()
Call this to set the segfault handler to Segfault::Handler.
Definition: Errors.h:310
const size_t ErrorMsg_text_size
The maximum size of the char array returned by ErrorMsg::what() and ErrorMsg::GetError(),...
Definition: Errors.h:38
const size_t ErrorMsg_type_bufsize
The maximum size of the char array returned by ErrorMsg::GetType(), including the null.
Definition: Errors.h:45