From 521027e1f566744a1b087cc3d047a714551d5f00 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rafa=C5=82=20D=C5=82ugo=C5=82=C4=99cki?= Date: Sat, 9 May 2015 11:57:15 +0200 Subject: [PATCH] Add try-catch block in example in order to fix memory leaks. Added specialized exceptions. --- include/exception/missingOptionValue.h | 29 ++++++++++++++++++++++ include/exception/optionFailedConversion.h | 29 ++++++++++++++++++++++ include/option.h | 19 +++++++------- src/main.cpp | 18 +++++++++----- 4 files changed, 79 insertions(+), 16 deletions(-) create mode 100644 include/exception/missingOptionValue.h create mode 100644 include/exception/optionFailedConversion.h diff --git a/include/exception/missingOptionValue.h b/include/exception/missingOptionValue.h new file mode 100644 index 0000000..c305005 --- /dev/null +++ b/include/exception/missingOptionValue.h @@ -0,0 +1,29 @@ +#ifndef __COMMAND_EXCEPTION_MISSING_OPTION_VALUE_H +#define __COMMAND_EXCEPTION_MISSING_OPTION_VALUE_H + +#include +#include + +namespace command { + +/** + * Helper template class used for releasing resources. + */ +class MissingOptionValue : public std::invalid_argument { +private: + std::string message; +public: + explicit MissingOptionValue(const std::string& what_arg) : + std::invalid_argument(what_arg), message(what_arg) { } + + explicit MissingOptionValue(const char* what_arg) : + std::invalid_argument(what_arg), message(what_arg) { } + + virtual const char* what() const throw() { + return message.c_str(); + } +}; + +} + +#endif /* __COMMAND_EXCEPTION_MISSING_OPTION_VALUE_H */ diff --git a/include/exception/optionFailedConversion.h b/include/exception/optionFailedConversion.h new file mode 100644 index 0000000..e4004f9 --- /dev/null +++ b/include/exception/optionFailedConversion.h @@ -0,0 +1,29 @@ +#ifndef __COMMAND_EXCEPTION_OPTION_FAILED_CONVERSION_H +#define __COMMAND_EXCEPTION_OPTION_FAILED_CONVERSION_H + +#include +#include + +namespace command { + +/** + * Helper template class used for releasing resources. + */ +class OptionFailedConversion : public std::invalid_argument { +protected: + std::string message; +public: + explicit OptionFailedConversion(const std::string& what_arg) : + std::invalid_argument(what_arg), message(what_arg) { } + + explicit OptionFailedConversion(const char* what_arg) : + std::invalid_argument(what_arg), message(what_arg) { } + + virtual const char* what() const throw() { + return message.c_str(); + } +}; + +} + +#endif /* __COMMAND_EXCEPTION_OPTION_FAILED_CONVERSION_H */ diff --git a/include/option.h b/include/option.h index 516fce0..21f814e 100644 --- a/include/option.h +++ b/include/option.h @@ -6,6 +6,8 @@ #include #include "parameter.h" +#include "exception/missingOptionValue.h" +#include "exception/optionFailedConversion.h" namespace command { /** @@ -79,29 +81,26 @@ namespace command { * converted to ParameterType, returns true and Option is set as used one. * Otherwise returns false and can be used to check against next value. * - * @throw std::invalid_argument when OptionName part has no equal sign - * after itself - * @throw std::invalid_argument when OptionValue part failed conversion + * @throw MissingOptionValue when OptionValue part is missing after + * equal sign + * @throw OptionFailedConversion when OptionValue part failed conversion * to ParameterType */ - virtual bool understand(const std::string & argv) - throw(std::invalid_argument) { + virtual bool understand(const std::string & argv) { if ((!isUsed()) && (argv.find(name) == 0)) { std::size_t pos = argv.find("="); if (pos != name.size()) { - throw std::invalid_argument("Option: " + name + " requires value but no one has been provided"); + throw MissingOptionValue("Option: " + name + " requires value but no one has been provided"); } std::stringstream ss; ss << argv.substr(pos + 1); - ss >> value;// memory leak? when uncommented and exception is - // thrown, valgrind shows e.g.: - // possibly lost: 380 bytes in 7 blocks + ss >> value; if (ss.fail()) { - throw std::invalid_argument("Value for option: " + name + " failed conversion to the required type"); + throw OptionFailedConversion("Value for option: " + name + " failed conversion to the required type"); } used = true; diff --git a/src/main.cpp b/src/main.cpp index 5cf4e83..42c44cb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,12 +21,18 @@ void void_function(void) { } int main(int argc, char *argv[]) { - Command command(argc, argv, { -// new Argument("File path", [](std::string value)->void { std::cout << "Hello from lambda " << value << std::endl; }), - new Required(new Argument("File path", argument_function)), - new Option("f", "Optional file", option_function), - new Option("h", "Help", void_function) - }); + try { + Command command(argc, argv, { +// new Argument("File path", [](std::string value)->void { std::cout << "Hello from lambda " << value << std::endl; }), + new Required(new Argument("File path", argument_function)), + new Option("f", "Optional file", option_function), + new Option("h", "Help", void_function) + }); + + } + catch(const std::exception & e) { + std::cout << e.what() << std::endl; + } return 0; } \ No newline at end of file -- 2.30.2