1 // Copyright (C) 2003 Davis E. King (davis@dlib.net) 2 // License: Boost Software License See LICENSE.txt for the full license. 3 #ifndef DLIB_ERROr_ 4 #define DLIB_ERROr_ 5 6 #include <string> 7 #include <new> // for std::bad_alloc 8 #include <iostream> 9 #include <cassert> 10 #include <cstdlib> 11 #include <exception> 12 13 // ------------------------------- 14 // ------ exception classes ------ 15 // ------------------------------- 16 17 namespace dlib 18 { 19 20 // ---------------------------------------------------------------------------------------- 21 22 enum error_type 23 { 24 EPORT_IN_USE, 25 ETIMEOUT, 26 ECONNECTION, 27 ELISTENER, 28 ERESOLVE, 29 EMONITOR, 30 ECREATE_THREAD, 31 ECREATE_MUTEX, 32 ECREATE_SIGNALER, 33 EUNSPECIFIED, 34 EGENERAL_TYPE1, 35 EGENERAL_TYPE2, 36 EGENERAL_TYPE3, 37 EINVALID_OPTION, 38 ETOO_FEW_ARGS, 39 ETOO_MANY_ARGS, 40 ESOCKET, 41 ETHREAD, 42 EGUI, 43 EFATAL, 44 EBROKEN_ASSERT, 45 EIMAGE_LOAD, 46 EDIR_CREATE, 47 EINCOMPATIBLE_OPTIONS, 48 EMISSING_REQUIRED_OPTION, 49 EINVALID_OPTION_ARG, 50 EMULTIPLE_OCCURANCES, 51 ECONFIG_READER, 52 EIMAGE_SAVE, 53 ECAST_TO_STRING, 54 ESTRING_CAST, 55 EUTF8_TO_UTF32, 56 EOPTION_PARSE 57 }; 58 59 // ---------------------------------------------------------------------------------------- 60 61 // the base exception class 62 class error : public std::exception 63 { 64 /*! 65 WHAT THIS OBJECT REPRESENTS 66 This is the base exception class for the dlib library. i.e. all 67 exceptions in this library inherit from this class. 68 !*/ 69 70 public: error(error_type t,const std::string & a)71 error( 72 error_type t, 73 const std::string& a 74 ): info(a), type(t) {} 75 /*! 76 ensures 77 - #type == t 78 - #info == a 79 !*/ 80 error(error_type t)81 error( 82 error_type t 83 ): type(t) {} 84 /*! 85 ensures 86 - #type == t 87 - #info == "" 88 !*/ 89 error(const std::string & a)90 error( 91 const std::string& a 92 ): info(a), type(EUNSPECIFIED) {} 93 /*! 94 ensures 95 - #type == EUNSPECIFIED 96 - #info == a 97 !*/ 98 error()99 error( 100 ): type(EUNSPECIFIED) {} 101 /*! 102 ensures 103 - #type == EUNSPECIFIED 104 - #info == "" 105 !*/ 106 ~error()107 virtual ~error( 108 ) throw() {} 109 /*! 110 ensures 111 - does nothing 112 !*/ 113 what()114 const char* what( 115 ) const throw() 116 /*! 117 ensures 118 - if (info.size() != 0) then 119 - returns info.c_str() 120 - else 121 - returns type_to_string(type) 122 !*/ 123 { 124 if (info.size() > 0) 125 return info.c_str(); 126 else 127 return type_to_string(); 128 } 129 type_to_string()130 const char* type_to_string ( 131 ) const throw() 132 /*! 133 ensures 134 - returns a string that names the contents of the type member. 135 !*/ 136 { 137 if ( type == EPORT_IN_USE) return "EPORT_IN_USE"; 138 else if ( type == ETIMEOUT) return "ETIMEOUT"; 139 else if ( type == ECONNECTION) return "ECONNECTION"; 140 else if ( type == ELISTENER) return "ELISTENER"; 141 else if ( type == ERESOLVE) return "ERESOLVE"; 142 else if ( type == EMONITOR) return "EMONITOR"; 143 else if ( type == ECREATE_THREAD) return "ECREATE_THREAD"; 144 else if ( type == ECREATE_MUTEX) return "ECREATE_MUTEX"; 145 else if ( type == ECREATE_SIGNALER) return "ECREATE_SIGNALER"; 146 else if ( type == EUNSPECIFIED) return "EUNSPECIFIED"; 147 else if ( type == EGENERAL_TYPE1) return "EGENERAL_TYPE1"; 148 else if ( type == EGENERAL_TYPE2) return "EGENERAL_TYPE2"; 149 else if ( type == EGENERAL_TYPE3) return "EGENERAL_TYPE3"; 150 else if ( type == EINVALID_OPTION) return "EINVALID_OPTION"; 151 else if ( type == ETOO_FEW_ARGS) return "ETOO_FEW_ARGS"; 152 else if ( type == ETOO_MANY_ARGS) return "ETOO_MANY_ARGS"; 153 else if ( type == ESOCKET) return "ESOCKET"; 154 else if ( type == ETHREAD) return "ETHREAD"; 155 else if ( type == EGUI) return "EGUI"; 156 else if ( type == EFATAL) return "EFATAL"; 157 else if ( type == EBROKEN_ASSERT) return "EBROKEN_ASSERT"; 158 else if ( type == EIMAGE_LOAD) return "EIMAGE_LOAD"; 159 else if ( type == EDIR_CREATE) return "EDIR_CREATE"; 160 else if ( type == EINCOMPATIBLE_OPTIONS) return "EINCOMPATIBLE_OPTIONS"; 161 else if ( type == EMISSING_REQUIRED_OPTION) return "EMISSING_REQUIRED_OPTION"; 162 else if ( type == EINVALID_OPTION_ARG) return "EINVALID_OPTION_ARG"; 163 else if ( type == EMULTIPLE_OCCURANCES) return "EMULTIPLE_OCCURANCES"; 164 else if ( type == ECONFIG_READER) return "ECONFIG_READER"; 165 else if ( type == EIMAGE_SAVE) return "EIMAGE_SAVE"; 166 else if ( type == ECAST_TO_STRING) return "ECAST_TO_STRING"; 167 else if ( type == ESTRING_CAST) return "ESTRING_CAST"; 168 else if ( type == EUTF8_TO_UTF32) return "EUTF8_TO_UTF32"; 169 else if ( type == EOPTION_PARSE) return "EOPTION_PARSE"; 170 else return "undefined error type"; 171 } 172 173 const std::string info; // info about the error 174 const error_type type; // the type of the error 175 176 private: 177 const error& operator=(const error&); 178 }; 179 180 // ---------------------------------------------------------------------------------------- 181 182 class fatal_error : public error 183 { 184 /*! 185 WHAT THIS OBJECT REPRESENTS 186 As the name says, this object represents some kind of fatal error. 187 That is, it represents an unrecoverable error and any program that 188 throws this exception is, by definition, buggy and needs to be fixed. 189 190 Note that a fatal_error exception can only be thrown once. The second 191 time an application attempts to construct a fatal_error it will be 192 immediately aborted and an error message will be printed to std::cerr. 193 The reason for this is because the first fatal_error was apparently ignored 194 so the second fatal_error is going to make itself impossible to ignore 195 by calling abort. The lesson here is that you should not try to ignore 196 fatal errors. 197 198 This is also the exception thrown by the DLIB_ASSERT and DLIB_CASSERT macros. 199 !*/ 200 201 public: fatal_error(error_type t,const std::string & a)202 fatal_error( 203 error_type t, 204 const std::string& a 205 ): error(t,a) {check_for_previous_fatal_errors();} 206 /*! 207 ensures 208 - #type == t 209 - #info == a 210 !*/ 211 fatal_error(error_type t)212 fatal_error( 213 error_type t 214 ): error(t) {check_for_previous_fatal_errors();} 215 /*! 216 ensures 217 - #type == t 218 - #info == "" 219 !*/ 220 fatal_error(const std::string & a)221 fatal_error( 222 const std::string& a 223 ): error(EFATAL,a) {check_for_previous_fatal_errors();} 224 /*! 225 ensures 226 - #type == EFATAL 227 - #info == a 228 !*/ 229 fatal_error()230 fatal_error( 231 ): error(EFATAL) {check_for_previous_fatal_errors();} 232 /*! 233 ensures 234 - #type == EFATAL 235 - #info == "" 236 !*/ 237 238 private: 239 message()240 static inline char* message () 241 { 242 static char buf[2000]; 243 buf[1999] = '\0'; // just to be extra safe 244 return buf; 245 } 246 dlib_fatal_error_terminate()247 static inline void dlib_fatal_error_terminate ( 248 ) 249 { 250 std::cerr << "\n**************************** FATAL ERROR DETECTED ****************************"; 251 std::cerr << message() << std::endl; 252 std::cerr << "******************************************************************************\n" << std::endl; 253 } 254 check_for_previous_fatal_errors()255 void check_for_previous_fatal_errors() 256 { 257 // If dlib is being use to create plugins for some other application, like 258 // MATLAB, then don't do these checks since it terminates the over arching 259 // system. Just let the errors go to the plugin handler and it will deal with 260 // them. 261 #if defined(MATLAB_MEX_FILE) || defined(DLIB_NO_ABORT_ON_2ND_FATAL_ERROR) 262 return; 263 #else 264 static bool is_first_fatal_error = true; 265 if (is_first_fatal_error == false) 266 { 267 std::cerr << "\n\n ************************** FATAL ERROR DETECTED ************************** " << std::endl; 268 std::cerr << " ************************** FATAL ERROR DETECTED ************************** " << std::endl; 269 std::cerr << " ************************** FATAL ERROR DETECTED ************************** \n" << std::endl; 270 std::cerr << "Two fatal errors have been detected, the first was inappropriately ignored. \n" 271 << "To prevent further fatal errors from being ignored this application will be \n" 272 << "terminated immediately and you should go fix this buggy program.\n\n" 273 << "The error message from this fatal error was:\n" << this->what() << "\n\n" << std::endl; 274 using namespace std; 275 assert(false); 276 abort(); 277 } 278 else 279 { 280 // copy the message into the fixed message buffer so that it can be recalled by dlib_fatal_error_terminate 281 // if needed. 282 char* msg = message(); 283 unsigned long i; 284 for (i = 0; i < 2000-1 && i < this->info.size(); ++i) 285 msg[i] = info[i]; 286 msg[i] = '\0'; 287 288 // set this termination handler so that if the user doesn't catch this dlib::fatal_error that is being 289 // thrown then it will eventually be printed to standard error 290 std::set_terminate(&dlib_fatal_error_terminate); 291 } 292 is_first_fatal_error = false; 293 #endif 294 } 295 }; 296 297 // ---------------------------------------------------------------------------------------- 298 299 class gui_error : public error 300 { 301 public: gui_error(error_type t,const std::string & a)302 gui_error( 303 error_type t, 304 const std::string& a 305 ): error(t,a) {} 306 /*! 307 ensures 308 - #type == t 309 - #info == a 310 !*/ 311 gui_error(error_type t)312 gui_error( 313 error_type t 314 ): error(t) {} 315 /*! 316 ensures 317 - #type == t 318 - #info == "" 319 !*/ 320 gui_error(const std::string & a)321 gui_error( 322 const std::string& a 323 ): error(EGUI,a) {} 324 /*! 325 ensures 326 - #type == EGUI 327 - #info == a 328 !*/ 329 gui_error()330 gui_error( 331 ): error(EGUI) {} 332 /*! 333 ensures 334 - #type == EGUI 335 - #info == "" 336 !*/ 337 }; 338 339 // ---------------------------------------------------------------------------------------- 340 341 class socket_error : public error 342 { 343 public: socket_error(error_type t,const std::string & a)344 socket_error( 345 error_type t, 346 const std::string& a 347 ): error(t,a) {} 348 /*! 349 ensures 350 - #type == t 351 - #info == a 352 !*/ 353 socket_error(error_type t)354 socket_error( 355 error_type t 356 ): error(t) {} 357 /*! 358 ensures 359 - #type == t 360 - #info == "" 361 !*/ 362 socket_error(const std::string & a)363 socket_error( 364 const std::string& a 365 ): error(ESOCKET,a) {} 366 /*! 367 ensures 368 - #type == ESOCKET 369 - #info == a 370 !*/ 371 socket_error()372 socket_error( 373 ): error(ESOCKET) {} 374 /*! 375 ensures 376 - #type == ESOCKET 377 - #info == "" 378 !*/ 379 }; 380 381 // ---------------------------------------------------------------------------------------- 382 383 class thread_error : public error 384 { 385 public: thread_error(error_type t,const std::string & a)386 thread_error( 387 error_type t, 388 const std::string& a 389 ): error(t,a) {} 390 /*! 391 ensures 392 - #type == t 393 - #info == a 394 !*/ 395 thread_error(error_type t)396 thread_error( 397 error_type t 398 ): error(t) {} 399 /*! 400 ensures 401 - #type == t 402 - #info == "" 403 !*/ 404 thread_error(const std::string & a)405 thread_error( 406 const std::string& a 407 ): error(ETHREAD,a) {} 408 /*! 409 ensures 410 - #type == ETHREAD 411 - #info == a 412 !*/ 413 thread_error()414 thread_error( 415 ): error(ETHREAD) {} 416 /*! 417 ensures 418 - #type == ETHREAD 419 - #info == "" 420 !*/ 421 }; 422 423 // ---------------------------------------------------------------------------------------- 424 425 class impossible_labeling_error : public dlib::error 426 { 427 /*! 428 WHAT THIS OBJECT REPRESENTS 429 This is the exception thrown by code that trains object detectors (e.g. 430 structural_svm_object_detection_problem) when they detect that the set of 431 truth boxes given to the training algorithm contains some impossible to 432 obtain outputs. 433 434 This kind of problem can happen when the set of image positions scanned by 435 the underlying object detection method doesn't include the truth rectangle 436 as a possible output. Another possibility is when two truth boxes are very 437 close together and hard coded non-max suppression logic would prevent two 438 boxes in such close proximity from being output. 439 !*/ 440 public: impossible_labeling_error(const std::string & msg)441 impossible_labeling_error(const std::string& msg) : dlib::error(msg) {}; 442 }; 443 444 // ---------------------------------------------------------------------------------------- 445 446 } 447 448 #endif // DLIB_ERROr_ 449 450