I have a code design question.
My question is where should I place my user error handling code and what method should I use.
The situation is this, my user should provide a file name to a function, this function then tries to open the file and manipulate it. Should the file not exist I would like to notify the user and try again with a newly inputted file name. As I understand std exception handling is not a suitable solution for this case.
Now I believe I have a couple of options; check the file exists before calling the function,
check whether it exists within the function and return a true false to indicate whether it was successful, or check whether it exists within the file if not calling a function which prints the message and allows the name to be changed before returning to the original function.
Which of these methods is preferred and why, is there a better alternative/lib functionality I should be using.
Thanks in advance and sorry if the question is inconsequential but I like to try and get these things right.
Usually, you should try to open the file once you've got the filename, and loop if that fails. And the function should take an std::istream&, and not the filename. At least in the small scenario you show. Alternatively, the function can take the filename, and return an error code indicating whether it was unable to open the file or not. And there are cases (not very frequent, but they do exist) where the alternatives to using an exception have even more disadvantages, so the exception would be the most appropriate solution.
I wouldn't disregard exceptions that easily and say that they are not suitable. It just depends on the overall design - e.g. whether your client has exception handling enabled or not. You can build your exception class hierarchy and have let's say CFileException (inherited from std::exception) and then CFileNotFoundException, CFileAccessDeniedException...etc....inherited from it. If your client is happy to handle this type of exceptions - use them! You can pass more information about the error within the exception object than in the error code plus your client can decide where will that exception be handled.
The other solution is to return different error codes for different errors. Don't just return true/false - it will not give much information to the client (why did function fail). Client will need to test error code and produce message (error description, error cause) to the user accordingly. If you use exception instead, that message could be created in the function that failed - which is the context that contains more information about the error and its nature and so can create more descriptive message.
Regarding the breaking your function into smaller ones: you said "function then tries to open the file and manipulate it" so it would be worth having two separate functions - one which opens file and another which process it. The same rules for exception/errors apply - if opening file fails, exception will be thrown and the second would not be entered.
If you need specific input for a function, you should always check the arguments inside of the function if unexpected arguments will result in unexpected behavior, except your trying to build a high performance application. That's what std::invalid_argument in <stdexcept> is for.
Of course you should always try to ensure that the arguments you provide to your procedures are correct. But it doesn't harm you if your function can tell you that something is currently going wrong. Since your program can't read std::cout you have to stick to exceptions or return error codes.
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <string>
void myFunction(const std::string& inputFileName){
std::ifstream myFile(inputFileName.c_str());
if(!myFile.good())
throw std::invalid_argument("The file does not exist!\n");
/* other operations */
}
int main(){
std::string userInput;
std::cin >> userInput;
while(userInput != "quit"){
try{
myFunction(userInput);
}catch(const std::invalid_argument& e){
std::cout << e.what();
}
std::cin >> userInput;
}
return 0;
}
/* this code is just a small example and could be improved */
Related
I am using exit in C++ void function if file cannot be opened. Is it good practice to do so?
void ReadData()
{
ofstream myfile ("example.txt");
if (! myfile.is_open())
{
cout << "Unable to open file";
exit(0);
}
else {
myfile << "This is a line.\n";
myfile << "This is another line.\n";
myfile.close();
}
}
That will end the program, which is a bit harsh if the caller might be able to handle the error and continue. Exiting with zero (indicating success) is a very bad idea.
The usual way to report an error in C++ is to throw an exception. Then the caller can choose whether to handle it, or whether to ignore it and perhaps terminate the program.
Generally, a reusable function should not abort or exit the program unless you know the caller will be unable to handle the failure in any reasonable way. Otherwise, it is "rude" to your caller to exit because of a failure that the caller could handle.
For example, a function that looks for a given file may fail because the file doesn't exist, but maybe the file is optional (a cache file, for example), in which case the failure is harmless to the caller.
Instead of exiting, consider returning an error code or throwing an exception instead.
If you choose to use exit, you will want to use something other than 0, such as
exit(1);
The good thing about this is that a script calling your program can detect an error easily with the return code.
If you plan to write code that others will use, it isn't a good practice to use exit(). At worse, it can get you in a lot of trouble with your customer or user base.
Case in point: There was a commercial database library some time ago that took this approach of exiting the application if something went wrong. Needless to say, there were a lot of complaints by the users of the library, and the arrogance that the authors showed concerning this basically put them on the outs with their users.
Bottom line is that it shouldn't be up to you (the library author) to decide to pull the rug out from under a running program just because you feel the error is severe. Instead return an error or throw an exception.
Does anyone know a opensource c++ application with a well designed/robust exception mechanism so I can get some inspiration? Most code/examples I see do questionable things like:
Throw objects with a message string as argument. Seems wrong because it marks the exception as fatal, a error message wich can be displayed to the user higher up leaves little room for client code trying to handle the exception. Even if the exception is fatal, things like diffirent locales (languages) makes formatting a message at the point of throw seem like a bad idea to me.
Use tons of different exception classes derived from a base exception class. Just feels wrong introducing a new class/type for every single thing that can go wrong (open file, read file, write file, create thread, etc...). Catching all unhandled exceptions at the highest level using the base type loses type information required to display meaningfull error messages.
Use one exception class derived from a base exception class for every component/library and give it a error code as argument to indicate the exact error. Catching with base type results in ambiguity. (Whose error code "3" did we catch? )...
Some pointers in the right direction would be welcome.
To address all three of these, I found that the best for me is to throw my own custom exception that's derived from std::runtime_error. Like this:
#include <exception>
class ChrisAException : public std::runtime_error
{
/// constructor only which passes message to base class
ChrisAException(std::string msg)
: std::runtime_error(msg)
{
}
}
It allows accepting a string, which I always put in something like the following format (assuming x negative was not a valid input and meant something calling it was in error):
#include "ChrisAException.h"
void myfunction(int x)
{
if(x < 0)
{
throw ChrisAException("myfunction(): input was negative!");
}
// rest of your function
}
For this one, keep in mind that the strings in these exceptions are more for the programmer than the end user. It's the programmer of the interface's job to display something meaningful in the locale when there's a failure. The strings in the exception can either be logged or seen at debug time (preferable!)
This way you can ultimately catch it with:
try
{
// high level code ultimately calling myfunction
}
catch(ChrisAException &cae)
{
// then log cae.what()
}
catch(std::runtime_error &e)
{
// this will also catch ChrisAException's if the above block wasn't there
}
catch(...)
{
// caught something unknown
}
I personally don't like deriving too many types of exceptions, or giving an error code. I let the string message do the reporting.
In general, I use C++ exceptions to mean "something went wrong with the program" and not to handle normal use cases. Thus, for me, a thrown exception during the algorithm execution either means "flag the user that something went wrong" or "don't tell the user" (depending on how critical that code was to what they were doing) but certainly log it and let the programmers know somehow.
I don't use C++ exceptions to handle cases that aren't essentially programming errors, e.g., some kind of incorrect logic or something being called wrong. For example, I wouldn't use C++ exceptions to handle normal program situations like an empty DVD not being in the drive for a DVD writing program. For that, I'd have explicit return code that allows the user to know whether an empty DVD was there (maybe with a dialog etc.)
Keep in mind that part of C++ exception handling is to unwind the stack up to a try-catch block. To me that means, abort what's going on in the program and clean up the stack. In the case of something like my DVD example, you shouldn't really want to unwind much of the stack. It wasn't catastrophic. You should simply let the user know and then let them try again.
But again, this is my preferred way of using C++ exceptions, based on experience and my reading. I'm open to opinions otherwise.
edit: Changed std::exception to std::runtime_error based on commenter advice.
I was told in a comment in another thread that I should be using exceptions whenever anything out of the ordinary happens, even if it isn't fatal to the script. This came up as I was using constructs akin to the following:
return err("File could not be loaded");
which would print the error to the screen, and return false, terminating the instruction processing. It was suggested that this would be better handled with exceptions.
The trouble is that the program is, for all intents and purposes, a language interpreter, controlled through a console, which means that any time a command is input incorrectly, or there is a bug in the interpreted code, an error needs to be displayed.
Besides the fact that these issues seem to minor to be processed as exceptions, how should it be implemented? How can a try block be used to control processing paths? For example, currently my code looks as follows:
if(!validate(code))
return false; //the validate function already having output the error
else
process(code);
How should I ensure that process(code) only executes if validate(code) succeeds? Should I just return false; from the function in the catch block? This would seem to return to the original issue of using return values to handle exceptional events. It seems to me that the fundamental problem is that the issues aren't exceptions at all, but I defer to those with more experience than I.
If an operation may - by design - either succeed or fail, and both of those are common, it might be most clear to structure your command flow in such way that errors are checked "explicitly", like in boolean value of "validate" function.
Exceptions come in handy when you don't want to disturb your regular control flow with error checking and want to move the checking somewhere else, maybe some function call levels above.
Your situation sounds like you don't really need exceptions. If your code looks clean without them, stay with it.
The idea of exceptions is you wouldn't need something like a separate "validate" step. Whenever "process" gets to a point where something's broken, throw an exception.
If you did need a separate validation step for some reason, then it'd look like
validate(code);
process(code);
Validate would throw an exception on failure, in which case process would never be reached.
try
{
validate(code);
process(code);
}
catch(...)
{
return false;
}
return true;
Assuming that validate throws, process won't happen.
Maybe you want your top-level loop to look something like this:
while (!quit) {
try {
process_command_line_input();
}
catch (const std::exception& ex) {
std::cerr << "Error: " << ex.what() << std::endl;
}
}
So, process_command_line_input() gets the next line of input and does whatever it does. If any error is detected, an exception is thrown, the top level loop displays it, and then goes on to the next input line.
The issue is that you have your function set up to use a return code. You can't just drag and drop exceptions in when your code is already set up with return values.
The correct way to do it is like
std::string code;
// input into code
try {
validate(code);
process(code); // Throws an exception.
}
catch(std::runtime_error& except) {
std::cout << except.what();
// recover from here.
}
There is no one correct answer.
It is highly dependent on the code and the situation:
In your situation the simple code above (if it is withing my own class) then error codes are fine:
class MyClass
{
public:
void processesValidCodesOrIgnore(int code)
{
if (validate(code))
{
processesCode(code);
}
}
private:
bool validate(int);
void processesCode(int);
};
As the validate method is private I know its result will always be checked and not ignored so its very easy to just use error codes in this situation.
On the other hand if validate was public I would definately consider using exceptions (depending on usage). As this would force the caller to actively check for problems rather than silently ignoring them.
I've a class called TFile, and I can't (don't want to) modify it. It doesn't throw exception if the input/output file is not found but I can check the iternal status using the method IsZombie. Now, I've implemented a very simple exception:
class FileNotFoundError : public std::runtime_error
{
public :
FileNotFoundError(const std::string & file_name="")
: runtime_error("cannot find file " + file_name), filename(file_name) {};
string filename;
~FileNotFoundError() throw() {};
};
and I use it as:
f = new TFile(total.c_str(), "RECREATE") ;
if (f->IsZombie())
{
throw FileNotFoundError(total);
}
is there a better way to implement this exception, I mean: is it userful to throw a standard exception as ifstream::failure instead of my custom exception?
There is no std exception that gives you a highly selective way to catch a 'file not found' error condition. So, yes, if you want to signal that condition with an exception and you want to allow the client code to do something meaningful then you need to create your own class for that.
There is however also a reason why that exception doesn't already exist, even though it is by far the most common mishap. It's kinda normal that a file isn't there when you expect it to be. Your program is not in control of the file system. Or maybe the user typed the file name wrong, something like that. It isn't really exceptional that this goes wrong. Don't use exceptions for non-exceptional cases.
This is a mixed message. Do use it when the client code had a reasonable way to check for itself that the file should exist and continuing program execution without that resource is unlikely.
In C++, RAII is often advocated as a superior approach to exception handling: if an exception is thrown, the stack is unwound, all the destructors are called and resources are cleaned up.
However, this presents a problem with error reporting. Say a very generic function fails, the stack is unwound to the top level and all I see in the logs would be:
Couldn't read from socket: connection reset by peer.
...or any equally generic message. This doesn't say much about the context from which the exception is thrown. Especially if I'm running something like an event queue processing loop.
Of course I could wrap every call to socket reads with a try/catch block, catch the exception, construct a new one with more detailed context information and re-throw it, but it defeats the purpose of having RAII, and is slowly but surely becoming worse than handling return error codes.
What's a better way for detailed for error reporting in standard C++? I'm also open to suggestions involving Boost.
As James McNellis suggested here, there is a really neat trick involving a guard object and the std::uncaught_exception facility.
The idea is to write code like this:
void function(int a, int b)
{
STACK_TRACE("function") << "a: " << a << ", b: " << b;
// do anything
}
And have the message logged only in case an exception is actually thrown.
The class is very simple:
class StackTrace: boost::noncopyable // doesn't make sense to copy it
{
public:
StackTrace(): mStream() {}
~StackTrace()
{
if (std::uncaught_exception())
{
std::cout << mStream.str() << '\n';
}
}
std::ostream& set(char const* function, char const* file, unsigned int line)
{
return mStream << file << "#" << line << " - " << function << " - ";
}
private:
std::ostringstream mStream;
};
#define STACK_TRACE(func) \
StackTrace ReallyUnwieldyName; \
ReallyUnwieldyName.set(func, __FILE__, __LINE__)
One can use __PRETTY_FUNC__ or equivalent to avoid naming the function, but I have found in practice that it was too mangled / verbose for my own taste.
Note that you need a named object if you wish it to live till the end of the scope, which is the purpose here. We could think of tricky ways to generate a unique identifier, but I have never needed it, even when protecting narrower scope within a function, the rules of name hiding play in our favor.
If you combine this with an ExceptionManager (something where exceptions thrown register themselves), then you can get a reference to the latest exception and in case of logging you can rather decide to setup your stack within the exception itself. So that it's printed by what and ignored if the exception is discarded.
This is a matter of taste.
Note that in the presence of ExceptionManager you must remain aware that not all exceptions can be retrieved with it --> only the ones you have crafted yourself. As such you still need a measure of protection against std::out_of_range and 3rd party exceptions.
Say a very generic function fails, the stack is unwound to the top level and all I see in the logs would be [...]
What's a better way for detailed for error reporting in standard C++?
Error handling isn't local to a class or library - it is a application level concern.
Best I can answer you question is that the error reporting should be always implemented by looking first and foremost at the error handling. (And the error handling also including the handling of the error by the user.) Error handling is the decision making about what has to be done about the error.
That is one of the reasons why error reporting is an application level concern and strongly depends on the application workflow. In one application the "connection reset by peer" is a fatal error - in another it is a norm of life, error should be silently handled, connection should be reestablished and pending operation retried.
Thus the approach you mention - catch the exception, construct a new one with more detailed context information and re-throw it - is a valid one too: it is up to the top level application logic (or even user configuration) to decide whether the error is really an error or some special (re)action has to taken upon the condition.
What you have encountered is one of the weaknesses of so called out-of-line error handling (aka exceptions). And I'm not aware of any way to do it better. Exceptions create a secondary code path in the application and if error reporting is vital the design of the secondary code path has to treated just like the main code path.
Obvious alternative to the out-of-line error handling is the in-line error handling - good ol' return codes and log messages on the error conditions. That allows for a trick where application saves all low-severity log messages into internal (circular) buffer (of fixed or configurable size) and dumps them into the log only if high-severity error happens. This way more context information is available and different layers of application do not have to be actively aware of each other. That is also standard (and sometimes literally "standard" - mandated by law) way of error reporting in application fields like safety and mission critical software, were one is not allowed to miss errors.
I've never actually done this, but you could roll your own "stacktrace":
struct ErrorMessage {
const char *s;
ErrorMessage(const char *s) : msg(s) {}
~ErrorMessage() { if (s) std::cout << s << "\n"; }
void done() { s = 0; }
};
void someOperation() {
ErrorMessage msg("Doing the first bit");
// do various stuff that could throw
msg = "Doing the second bit";
// do more stuff that could throw
msg.done();
}
You can have several levels of this (although not necessarily use it at every level):
void handleFoo() {
ErrorMessage msg("Handling foo event");
someOperation();
msg.done();
}
And add more constructors and members:
void handleBar(const BarEvent &b) {
ErrorMessage msg(std::stringstream("Handling bar event ") << b.id);
someOperation();
msg.done();
}
And you needn't write the messages to std::cout. It could be to some logging object, and the object could queue them, and not actually output them to the log unless the catch site tells it to. That way, if you catch an exception that doesn't warrant logging, nothing is written.
It's not pretty, but it's prettier than try/catch/throw or checking return values. And if you forget to call done on success (for example if your function has multiple returns and you miss one), then you will at least see your mistake in the logs, unlike a resource leak.
[Edit: oh, and with a suitable macro you can store __FILE__ and __LINE__ in the ErrorMessage.]
You could add a call stack to your exception. I'm not sure how good this works for release builds but works like a charm with debug. You could do this in the constructor of your exception (to encapsulate it). See here for a starting point. This is possible as well on Linux - eventhough I dont remember how exactly.
I use RAII and exceptions and just have various unit-test-like assert statements throughout the code - if they fail, the the stack unwinds to where I can catch and handle them.
#define APP_ASSERT_MSG(Class,Assertion,szDescription) \
if ( !(Assertion) ) \
{ \
throw Class(__LINE__,__FILE__,szDescription); \
}
For most of my particular use case, all I care about is logging debug information, so my exception has the file and line number in it along with an error message (message is optional as I have an assert without it as well). You could easily add FUNCTION or an error code of some type for better handling.
I can then use it like this:
int nRet = download_file(...);
APP_ASSERT_MSG(DownloadException == ERR_OK, "Download failed");
This makes error handling and reporting much easier.
For really nasty debugging, I used GCC's function instrumentation to keep a trace list of what's going on. It works well, but slows down the app quite a bit.
What I do regularly, FWIW, is not use exceptions, but rather explicit error handling in a standard format (ie: using a macro). For example:
result = DoSomething();
CHECK_RESULT_AND_RETURN_ON_ERROR( result );
Now, obviously, this has many limitations design-wise:
Your return codes may need to be somewhat uniform
Code is cluttered with macros
You may need many macros for various check conditions
The upside, though, is as Dummy00001 said: you can effectively generate a stack trace on demand in the event of a serious error, by simply caching the results. I also use this paradigm to log all unexpected error conditions, so I can adjust the code later to handle unexpected conditions which occur "in the wild".
That's my 2c.
Here's how I handle error reporting in my libraries (this may or may not suit your situation).
First, as part of your design you want a "core" or "system" library that all this common logic will sit in. All you other libraries will then link to the core and use its error reporting APIs, so your whole system has a single compact chunk of logic for handling this mess.
Inside the core, provide a set of logging MACROS such as "LogWarning" and "LogFatal" with documented behavior and expected usage- for example, LogFatal should trigger a hard abort of the process but anything lower than "LogError" is simply advisory (does nothing). The macros can provide a "printf" interface that automatically appends the "LINE", "FILE", and "FUNC" macros as arguments to the underlying singleton object that handles your error reporting.
For the object itself I'll defer to you. However, you want public APIs that configure your "drains"- e.g. log to stderr, log to logfile, log to MS Services log, etc. You also want the underlying singleton to be thread safe, re-entrant where possible, and very robust.
With this system, you can make "exception reporting" ONE MORE DRAIN TYPE. Just add an internal API to that error manager object that packages your logged message as an exception, then throws it. Users can then enable AND DISABLE exceptions-on-error behavior in your code with ONE LINE in their apps. You can put try-catches around 3rd party or system code in you libraries that then calls a "Log..." macro in the catch clauses to enable clean re-throw behavior (with certain platforms and compiler options you can even catch things like segfaults using this).