error.dox
5.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// 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 T> class foo {
foo() { KALDI_ASSERT_IS_INTEGER_TYPE(T);
};
...
template<class T> 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.
*/
}