Quiz 13 — Exception Handling¶
Ten questions on making failure part of the design — and on the three ways exception handling usually goes wrong: catching by value, throwing from a destructor, and leaking on the way out.
Attempt all of them closed-book, then mark yourself against the answers.
Concepts: throw/catch · custom exceptions · catching by reference · stack
unwinding · the basic, strong and nothrow guarantees · destructors and noexcept.
Q1. (MCQ) When an exception leaves a scope, what happens to that scope's local objects?
- A. nothing; they leak
- B. they are destroyed, in reverse order of construction
- C. only those with a virtual destructor
- D. the program terminates
Q2. (true/false) A destructor that throws during stack unwinding causes
std::terminate.
Q3. (multiple-select) Which are the three exception-safety guarantees? Select all that apply.
- A. Basic — invariants hold, no leaks
- B. Strong — the operation either succeeds or has no effect
- C. Nothrow — the operation never throws
- D. Delayed — the exception is stored and thrown later
Q4. (predict) Write the two output lines.
#include <iostream>
#include <stdexcept>
int main() {
try {
throw std::runtime_error("boom");
}
catch (const std::logic_error&) {
std::cout << "logic\n";
}
catch (const std::runtime_error& e) {
std::cout << "runtime: " << e.what() << '\n';
}
std::cout << "after\n";
}
Q5. (predict) Write the output in order.
#include <iostream>
#include <stdexcept>
void inner() {
throw std::out_of_range("limit");
}
int main() {
try {
try {
inner();
}
catch (const std::out_of_range& e) {
std::cout << "inner " << e.what() << '\n';
throw;
}
}
catch (const std::exception& e) {
std::cout << "outer " << e.what() << '\n';
}
std::cout << "end\n";
}
Q6. (debug) Why does e.field() fail to compile, and what is the fix?
#include <iostream>
#include <stdexcept>
#include <string>
class ValidationError : public std::runtime_error {
public:
explicit ValidationError(std::string field)
: std::runtime_error("invalid " + field), field_(std::move(field)) {}
const std::string& field() const { return field_; }
private:
std::string field_;
};
int main() {
try {
throw ValidationError{"email"};
}
catch (std::runtime_error e) {
e.field();
}
}
Q7. (analysis) A Guard destructor throws when the stack is already unwinding.
Describe what the program does, and state the rule this demonstrates.
Q8. (short answer) What does the strong guarantee promise, and how is it different from the basic guarantee?
Q9. (design) An order pipeline fails four ways: unknown customer, out of stock,
invalid discount, payment timeout. Callers must retry any timeout with one catch and
handle any invalid order with another. Sketch the hierarchy and say which type carries
which extra data.
Q10. (analysis) A function news a buffer, does work, and may throw before it
frees the buffer. Which guarantee does it currently provide, and what change moves it to
the strong guarantee?
Scoring: mark yourself with the answers, then read the self-assessment guide.