From: Rafał Długołęcki Date: Tue, 5 May 2015 21:08:01 +0000 (+0200) Subject: Fix memory leaks, fix tests. X-Git-Tag: v0.2~19 X-Git-Url: https://git.dlugolecki.net.pl/?p=command.git;a=commitdiff_plain;h=9bc6a44ad1a07a6420ce4fd75dfea0796bcd0d46 Fix memory leaks, fix tests. --- diff --git a/include/argument.h b/include/argument.h index 53dea34..b07ae67 100644 --- a/include/argument.h +++ b/include/argument.h @@ -25,7 +25,7 @@ namespace command { /** Variable indicating if current Argument was already used or not */ bool used = false; - ArgumentType argument; + ArgumentType value; public: typedef class Argument Type; @@ -48,7 +48,7 @@ namespace command { * */ virtual void handle() { - this->call(argument); + this->call(value); } /** @@ -72,7 +72,7 @@ namespace command { std::stringstream ss; ss << argv; - ss >> argument; + ss >> value; if (!ss.fail()) { used = true; diff --git a/include/callable.h b/include/callable.h index bf74377..544b371 100644 --- a/include/callable.h +++ b/include/callable.h @@ -24,6 +24,7 @@ namespace command { Callable(void (*function)(ArgumentType)) : func(function) { } + virtual ~Callable() { } protected: diff --git a/include/command.h b/include/command.h index ec08681..8ecb280 100644 --- a/include/command.h +++ b/include/command.h @@ -3,7 +3,6 @@ #include #include -#include #include "parameter.h" @@ -26,16 +25,20 @@ namespace command { Command(unsigned int argc, char *argv[], std::initializer_list params) : parameters(params) { - matchArguments(argc, argv); + try { + matchArguments(argc, argv); + } + catch(std::invalid_argument exception) { + releaseMemory(); + throw; + } } /** * Destructor. Releases allocated memory. */ ~Command() { - for (Parameter * parameter : parameters) { - delete parameter; - } + releaseMemory(); } protected: /** @@ -51,6 +54,19 @@ namespace command { } } } + + /** + * Releases acquired memory + */ + void releaseMemory() { + for (Parameter * parameter : parameters) { + if (parameter != NULL) { + delete parameter; + } + } + parameters.clear(); + parameters.shrink_to_fit(); + } }; } diff --git a/include/descriptive.h b/include/descriptive.h index 08be41e..33f62fd 100644 --- a/include/descriptive.h +++ b/include/descriptive.h @@ -8,7 +8,7 @@ namespace command { * Descriptive behaviour class. */ class Descriptive { - std::string description; + const std::string description; public: /** * Default constructor. @@ -19,12 +19,14 @@ namespace command { : description(description) { } + virtual ~Descriptive() { } + /** * Returns description of the current class. * * @return provided description for the class */ - std::string describe() { + const std::string & describe() { return description; } }; diff --git a/include/option.h b/include/option.h index a77d8f4..1156766 100644 --- a/include/option.h +++ b/include/option.h @@ -26,7 +26,7 @@ namespace command { /** * Current Option name */ - OptionName name; + const OptionName name; /** * Current Option value @@ -44,7 +44,7 @@ namespace command { * @param description Description of current Option * @param function Function used to handle current Option. */ - Option(std::string name, const std::string & description, void (*function)(OptionType)) + Option(const std::string & name, const std::string & description, void (*function)(OptionType)) : Parameter(description), Callable(function), name(name) { } @@ -87,18 +87,21 @@ namespace command { * @throw std::invalid_argument when OptionValue part failed conversion * to OptionType */ - virtual bool understand(const std::string & argv) { - if ((!used) && - (argv.find(name) == 0)) { + virtual bool understand(const std::string & argv) + throw(std::invalid_argument) { + + if ((!used) && (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"); } std::stringstream ss; - ss << argv.substr(pos + 1); - ss >> value; + ss >> value;// memory leak? when is uncommented, and exception is + // thrown, valgrind shows e.g.: + // possibly lost: 380 bytes in 7 blocks if (ss.fail()) { throw std::invalid_argument("Value for option: " + name + " failed conversion to the required type"); @@ -132,7 +135,7 @@ namespace command { /** * Current Option name */ - OptionName name; + const OptionName name; /** Variable indicating if current Option was already used or not */ bool used = false; @@ -145,15 +148,10 @@ namespace command { * @param description Description of current Option * @param function Function used to handle current Option. */ - Option(std::string name, const std::string & description, void (*function)(void)) + Option(const std::string & name, const std::string & description, void (*function)(void)) : Parameter(description), Callable(function), name(name) { } - /** - * - */ - virtual ~Option() { } - /** * */ diff --git a/include/parameter.h b/include/parameter.h index a96128c..1396f83 100644 --- a/include/parameter.h +++ b/include/parameter.h @@ -24,7 +24,8 @@ namespace command { Parameter(const std::string & description) : Descriptive(description) { } - virtual ~Parameter() {} + + virtual ~Parameter() { } /** * Method used for handling method calls linked with Argument or Option