Show Lecture.Old-fashionedErrorHandling as a slide show.
CS253 Old-fashioned Error Handling
The Old Days
- Before try/recover, throw/catch, and the like became popular,
many other methods of error handling were used.
- Many are still used.
Out-of-band value
#include "Loud.h"
#include <unistd.h>
Loud a='a';
int foo() {
Loud b('b');
if (getuid() != 0) // root?
return -1;
return 42;
}
int main() {
Loud c('c');
if (foo() < 0)
return 1;
Loud d('d');
return 0;
}
Loud::Loud() [c='a']
Loud::Loud() [c='c']
Loud::Loud() [c='b']
Loud::~Loud() [c='b']
Loud::~Loud() [c='c']
Loud::~Loud() [c='a']
That works, but …
- That works. However:
- You need an out-of-band value. This isn’t always possible.
- The caller of
foo()
needs to check for errors, and return early.
- So does his caller.
- So does his caller.
- …
exit
#include "Loud.h"
#include <unistd.h>
Loud a='a';
void foo() {
Loud b('b');
// MUST be super-user!
if (getuid() != 0)
exit(1);
}
int main() {
Loud c('c');
foo();
Loud d('d');
return 0;
}
Loud::Loud() [c='a']
Loud::Loud() [c='c']
Loud::Loud() [c='b']
Loud::~Loud() [c='a']
abort
#include "Loud.h"
#include <unistd.h>
Loud a='a';
void foo() {
Loud b('b');
if (getuid() != 0)
abort();
}
int main() {
Loud c='c';
foo();
Loud d='d';
return 0;
}
Loud::Loud() [c='a']
Loud::Loud() [c='c']
Loud::Loud() [c='b']
SIGABRT: Aborted
assert
#include "Loud.h"
#include <cassert>
#include <unistd.h>
Loud a('a');
void foo() {
Loud b('b');
assert(!getuid());
}
int main() {
Loud c('c');
foo();
Loud d('d');
return 0;
}
Loud::Loud() [c='a']
Loud::Loud() [c='c']
Loud::Loud() [c='b']
a.out: c.cc:9: void foo(): Assertion `!getuid()' failed.
SIGABRT: Aborted
Division by Zero
#include "Loud.h"
#include <unistd.h>
Loud a('a');
static int n = 0;
void foo() {
Loud b('b');
if (getuid() != 0)
n = 1/n;
}
int main() {
Loud c('c');
foo();
Loud d('d');
return 0;
}
Loud::Loud() [c='a']
Loud::Loud() [c='c']
Loud::Loud() [c='b']
SIGFPE: Floating point exception
The Horror That Is Setjmp/Longjmp
#include <csetjmp>
#include <iostream>
#include "Loud.h"
using namespace std;
Loud a('a');
jmp_buf env;
void foo() {
Loud b('b');
longjmp(env, 456);
}
int main() {
if (int val = setjmp(env)) {
cout << "error=" << val << "!\n";
return 1;
}
Loud c('c');
foo();
Loud d('d');
return 0;
}
Loud::Loud() [c='a']
Loud::Loud() [c='c']
Loud::Loud() [c='b']
error=456!
Loud::~Loud() [c='a']