Errors
"Errors"
what are
?
"Errors"
what are
?
How are errors reported in code?
What behavior is considered erroneous?
"Errors"
what are
?
"a function couldn’t do what it advertised"
What behavior is considered erroneous?
arguments
state
do the job
side effects
result value
function
"Errors"
what are
?
What behavior is considered erroneous?
arguments
state
do the job
side effects
result value
function
arguments
do the job
result value
pure function
"Errors"
what are
?
What behavior is considered erroneous?
arguments
state
do the job
side effects
result value
function
Invalid Operation
Invalid Argument
Runtime Error
Out of Memory
"Errors"
what are
?
What behavior is considered erroneous?
Implementation Error
arguments
state
do the job
side effects
result value
Invalid Operation
Invalid Argument
arguments
state
do the job
side effects
result value
Invalid Operation
Invalid Argument
"Errors"
what are
?
What behavior is considered erroneous?
Runtime Error
Out of Memory
Runtime Error
Out of Memory
Implementation Error
Implementation Error
"Errors"
what are
?
What behavior is considered erroneous?
Invalid Operation
Invalid Argument
Runtime Error
Out of Memory
Implementation Error
out of bounds access, null pointer dereference, division by zero
pop from empty stack, write to immutable object, race condition
heap exhaustion
stack overflow, hardware failure, cannot open file, operating system complaint
not yet implemented, bug
"Errors"
what are
?
How are errors reported in code?
What behavior is considered erroneous?
"Errors"
what are
?
How are errors reported in code?
Termination
UB
abort assert
Invalid Operation
Invalid Argument
Implementation Error
Out of Memory
Runtime Error
Error codes
Exceptions
errno error_code
std::exception try, throw, catch noexcept
Out of Memory
Runtime Error
*Invalid Operation
*Invalid Argument
"Errors"
c#
-
Exception
-
InvalidOperationException
-
ArgumentException
-
IndexOutOfRangeException
-
NullReferenceException
-
StackOverflowException
-
OutOfMemeoryException
-
DivideByZeroException
- Do not use error codes
- Use exceptions
- Termination (for fatal error)
- Optional return (for performance)
- Document all throwable exceptions
- Mind performance, but use exceptions
"Errors"
c++
-
exception
-
UB or logic_error
-
UB, assert, logic_error
-
UB, assert, logic_error
-
UB, assert, logic_error
-
UB
-
UB, bad_alloc
-
UB, assert
- Some use error codes
- Some use exceptions
- Termination (for fatal error)
- Optional return (not for errors)
- noexcept if doesn't throw
- DESIRE PERFORMANCE
Undefined behavior
ill-formed
ill-formed; no diagnostic required (NDR)
undefined behavior (UB)
implementation defined behavior
unspecified behavior
Compile-time
Run-time
Undefined behavior
bool p;
if (p)
{
std::cout << "p";
}
if (!p)
{
std::cout << "!p";
}
bool will_increment_overflow(int x)
{
if (x + 1 < x)
{
return true;
}
return false;
}
bool will_increment_overflow(int x)
{
return false;
}
p!p
bool p = init_val();
if (p)
{
std::cout << "p";
}
if (!p)
{
std::cout << "!p";
}
bool will_increment_overflow(int x)
{
return x == std::numeric_limits<int>::max();
}
assertions
assert(condition)
static_assert(condition, message)
static_assert(condition)
- preconditions
- postconditions
- invariants
condition
Invalid Operation
Invalid Argument
Implementation Error
Termination
std::exit
std::quick_exit
std::_Exit std::terminate std::abort
std::atexit std::at_quick_exit - std::terminate_handler std::signal
- - - std::abort() -
function
handler
default handler
Exit Codes
-
EXIT_SUCCESS
-
EXIT_FAILURE
<cstdlib>
<cstdlib>
<cstdlib>
<cstdlib>
<exception>
<cstdlib>
[[noreturn]]
[[noreturn]] void Panic(std::string msg)
{
std::cerr << "Fatal error occured: " << msg;
std::abort();
}
Out of Memory
Runtime Error
error codes
void try_process_names()
{
file_t f;
int err = try_open_file("names.txt", &f);
if (err == FILE_ERROR)
{
std::cerr << "Cannot open file";
}
else
{
process(f);
}
}
int try_open_file(const char* path, file_t* t)
{
os_file_t* native_file = os_open_file(path);
if (os_file_t)
{
(*t) = wrap_native_file(native_file);
return NO_ERROR;
}
else
{
return FILE_ERROR;
}
}
error codes
errorCodeType readFile {
initialize errorCode = 0;
open the file;
if (theFileIsOpen) {
determine the length of the file;
if (gotTheFileLength) {
allocate that much memory;
if (gotEnoughMemory) {
read the file into memory;
if (readFailed) {
errorCode = -1;
}
} else {
errorCode = -2;
}
} else {
errorCode = -3;
}
close the file;
if (theFileDidntClose && errorCode == 0) {
errorCode = -4;
} else {
errorCode = errorCode and -4;
}
} else {
errorCode = -5;
}
return errorCode;
}
readFile {
try {
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
} catch (fileOpenFailed) {
doSomething;
} catch (sizeDeterminationFailed) {
doSomething;
} catch (memoryAllocationFailed) {
doSomething;
} catch (readFailed) {
doSomething;
} catch (fileCloseFailed) {
doSomething;
}
}
from (Oracle Java Tutorials)
Exceptions
errorCodeType readFile {
initialize errorCode = 0;
open the file;
if (theFileIsOpen) {
determine the length of the file;
if (gotTheFileLength) {
allocate that much memory;
if (gotEnoughMemory) {
read the file into memory;
if (readFailed) {
errorCode = -1;
}
} else {
errorCode = -2;
}
} else {
errorCode = -3;
}
close the file;
if (theFileDidntClose && errorCode == 0) {
errorCode = -4;
} else {
errorCode = errorCode and -4;
}
} else {
errorCode = -5;
}
return errorCode;
}
readFile {
try {
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
} catch (fileOpenFailed) {
doSomething;
} catch (sizeDeterminationFailed) {
doSomething;
} catch (memoryAllocationFailed) {
doSomething;
} catch (readFailed) {
doSomething;
} catch (fileCloseFailed) {
doSomething;
}
}
from (Oracle Java Tutorials)
Exceptions
void process_names()
{
try
{
file f = open_file("names.txt");
process(f);
}
catch(const std::exception& e)
{
std::cerr << e.what();
}
}
file_t open_file(const char* path)
{
os_file_t* native_file = os_open_file(path);
if (os_file_t)
{
return wrap_native_file(native_file);
}
else
{
throw std::runtime_error("Cannot open file");
}
}
Exceptions
void f() {
throw std::runtime_error();
}
void g() { f(); }
void h() { f(); }
void i() {
try {
h();
}
catch(const std::runtime_error& e) {
...
}
}
throw std::runtime_error();
throw 5;
throw "Hello world";
catch(...) {}
throw;
void f()
try {
}
catch (...) {
}
void f() {
try {
}
catch (const std::ios_base::failure& e) {
}
catch (const std::runtime_error& e) {
}
catch (const std::exception& e) {
}
catch (...) {
}
}
Exceptions
Exceptions vs error codes
Returning values or nothing
Database
entry
find(key)
Returning values or nothing
entry* find(const std::string& key) noexcept;
bool find(const std::string& key, entry& out) noexcept;
entry find(const std::string& key); // throw if not found
entry find(const std::string& key) noexcept; // assume that key is valid, ub if not found
struct result_t
{
entry result;
bool has_result;
}
result_t find(const std::string& key) noexcept;
Returning values or nothing
#include <optional>
std::optional<entry> find(const std::string& key) noexcept;
void useFind() {
auto result = find("Bob");
if (result) {
std::cout << "Bob has been found!";
std::cout << "Bob's data is" << *result;
}
if (result.has_value()) {
std::cout << "Bob has been found!";
std::cout << "Bob's data is" << result.value();
}
if (!result) {
std::cout << *result; // UB
std::cout << result.value(); // throw std::bad_optional_access
}
if (result == std::nullopt) {
std::cout << result.value_or("Bob not found");
}
}
Other error mechanisms
- signals
- floating point environment exceptions
- etc.
Errors
Errors
By Jan Bielak
Errors
A presentation about compilation errors, the as-if rule, undefined behavior, implementation defined behavior, error codes, std::optional, std::abort, exceptions. It is presented here: https://www.youtube.com/watch?v=ASOc73uTsdo .
- 715