// doc/error.dox // Copyright 2009-2011 Microsoft Corporation // See ../../COPYING for clarification regarding multiple authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, // MERCHANTABLITY OR NON-INFRINGEMENT. // See the Apache 2 License for the specific language governing permissions and // limitations under the License. namespace kaldi { /** \page error Kaldi logging and error-reporting \section error_overview Overview All output that consists of logging messages, warnings or errors is directed to the standard error in Kaldi programs. This is so that our programs can be used in of pipes without such messages becoming "mixed up" with the program's output. The most common way to produce logging, warning or error output is through the macros KALDI_LOG, KALDI_WARN and KALDI_ERR. Invoking the KALDI_ERR macro will normally terminate the program (unless the exception is caught). An example code fragment that illustrates all three of these is as follows: \code KALDI_LOG << "On iteration " << iter << ", objective function change was " << delta; if (delta < 0.0) { KALDI_WARN << "Negative objf change " << delta; if (delta < -0.1) KALDI_ERR << "Convergence failure in EM"; } \endcode Notice that these examples don't include a newline character (this gets added automatically). A typical example of the messages that get produced by this is: \verbatim WARNING (copy-feats:Next():util/kaldi-table-inl.h:381) Invalid archive file format \endverbatim For log messages that are not quite important enough (or are too verbose) to appear in normal logs, you can use KALDI_VLOG: for example, \code KALDI_VLOG(2) << "This message is not important enough to use KALDI_LOG for."; \endcode This will get printed if the argument to the \c --verbose option is greater than or equal to the number in parentheses, e.g. the message above would get printed if the user called a program with \c --verbose=2 or greater. See \ref parse_options_implicit for more context on this. Some parts of the code print logging messages to the standard error directly; this is discouraged. \section error_assertions Assertions in Kaldi Assertions should ideally be done using the macro KALDI_ASSERT. This prints more informative output than a normal assertion using assert(); KALDI_ASSERT prints a stack trace. KALDI_ASSERT is also more reconfigurable. A typical assertion is: \code KALDI_ASSERT(i < M.NumRows()); \endcode A trick that we sometimes to get more informative assert-failure message is to follow the assert condition with "&& [some string]", for example: \code KALDI_ASSERT(ApproxEqual(delta, objf_change) && "Probable coding error in optimization"); \endcode If compiled normally asserts will get checked, but not if compiled with NDEBUG defined. For inner-loop assertions that use a lot of CPU, we use the following pattern: \code #ifdef KALDI_PARANOID KALDI_ASSERT(i>=0); #endif \endcode The macro KALDI_PARANOID is on by default in the current build setup. \section error_exceptions Exceptions thrown by KALDI_ERR When the KALDI_ERR macro is invoked, it prints the error message to the standard error, and then throws an exception of type std::runtime_error. The string held by this exception contains the error message, and also a stack trace (if supported by the OS). The normal behavior of current Kaldi programs is to catch the exception in a try...catch block in main(), which prints the exception's string to the standard error, and exits. This typically results in the error message being printed twice. In some cases, the error message will be caught by Kaldi code and not re-thrown. This occurs in Holder code (see \ref io_sec_holders) that is called by Table code (see \ref io_sec_tables). Here, exceptions thrown by Read functions of Kaldi objects are caught and get propagated to the Table code as a boolean return value (e.g. see KaldiObjectHolder::Read() ). Depending on the \ref io_sec_rspecifiers "options", such as the "p" (permissive) option to the Table code, and depending how the Table code is called, this may or may not result in another exception. The only other type of error other than std::runtime_error that should get thrown in Kaldi code under normal circumstances is probably std::alloc_error. Some parts of Kaldi code currently throw std::runtime_error directly, or call assert() directly, but this is to be changed to the more standard KALDI_ERR and KALDI_ASSERT macros. \section error_compile_time_assertions Compile-time assertions in Kaldi It is also possible to make assertions that are checked at compile time (they will produce a compilation error if they fail). This is enabled by some macros defined in kaldi-utils.h. It is especially useful to make sure that templates have been instantiated with the right kind of types. Examples of compile-time assertions are: \code KALDI_COMPILE_TIME_ASSERT(kSomeConstant < 0); ... template class foo { foo() { KALDI_ASSERT_IS_INTEGER_TYPE(T); }; ... template class bar { bar() { KALDI_ASSERT_IS_FLOATING_TYPE(T); } \endcode */ /** \defgroup error_group "Functions relating to logging and error reporting" See \ref error_overview for an overview of how logging and errors are handled in Kaldi. */ }