It's a very sad truth that error checking is largely ignored in computer programming classes. When you're dealing with hardware, you really have no choice.
Even though your students haven't learned about passing by reference, they can still call functions that do it. You'll just have to explain to them that such a thing exists. As for the library, I suggest you follow a pattern like:
bool function(const InParams &in, OutParams &out);
The functions always return true on success and false on error. In addition, I'd include a thread-specific error variable:
struct Error {
int code;
string description;
stringstream context;
};
Error error;
Some people may gasp at the idea of a global, but it's really just following the errno concept from the C standard library.
- code is a numeric code like with errno. Each function sets it when there's an error.
- description is a text description of the error that happened.
- context says what was going on when the error happened. The nice thing about context is that if A() calls B() which calls C() which has an error, then each can set the context on the way up. Where I work, each function sets the context within that function. So A() might contain:
1 2 3 4
|
if (!B(bparam)) {
error.context << "A(" << aParams << ')';
return false;
}
|
This turns out to be a really powerful debugging tool. If yoused consistently, then when an error occurs, the context will say exactly what happened, where, and how you got there.
Does all this involve a lot of code? You bet it does! But that's what real code is. It involves a huge amount of error checking.
The other possibility is to use exceptions, but if the students haven't learned about call by reference, I doubt that they are ready for exceptions.