use std::auto_ptr wherever a thrown exception might otherwise leak memory

This commit is contained in:
John Wiegley 2004-08-19 03:28:48 -04:00
parent 965e1fc28f
commit bf923ab33e
8 changed files with 143 additions and 141 deletions

View file

@ -90,9 +90,9 @@ static void parse_inclusion_specifier(const std::string& word,
*end = interval_t(0, saw_mon ? 1 : 0, saw_year ? 1 : 0).increment(*begin);
}
interval_t * interval_t::parse(std::istream& in,
std::time_t * begin,
std::time_t * end)
interval_t interval_t::parse(std::istream& in,
std::time_t * begin,
std::time_t * end)
{
unsigned long years = 0;
unsigned long months = 0;
@ -203,7 +203,8 @@ interval_t * interval_t::parse(std::istream& in,
parse_inclusion_specifier(word, begin, end);
}
}
return new interval_t(seconds, months, years);
return interval_t(seconds, months, years);
}
bool parse_date_mask(const char * date_str, struct std::tm * result)

View file

@ -13,13 +13,18 @@ struct interval_t
int months;
int seconds;
interval_t(int _seconds, int _months = 0, int _years = 0)
interval_t(int _seconds = 0, int _months = 0, int _years = 0)
: years(_years), months(_months), seconds(_seconds) {}
operator bool() const {
return seconds > 0 || months > 0 || years > 0;
}
std::time_t increment(const std::time_t);
static interval_t * parse(std::istream& in, std::time_t * begin,
std::time_t * end);
static interval_t parse(std::istream& in,
std::time_t * begin,
std::time_t * end);
};
extern std::time_t now;

View file

@ -45,7 +45,8 @@ std::auto_ptr<value_expr_t> format_t::total_expr;
element_t * format_t::parse_elements(const std::string& fmt)
{
element_t * result = NULL;
std::auto_ptr<element_t> result;
element_t * current = NULL;
static char buf[1024];
@ -57,8 +58,9 @@ element_t * format_t::parse_elements(const std::string& fmt)
continue;
}
if (! result) {
current = result = new element_t;
if (! result.get()) {
result.reset(new element_t);
current = result.get();
} else {
current->next = new element_t;
current = current->next;
@ -148,8 +150,9 @@ element_t * format_t::parse_elements(const std::string& fmt)
}
if (q != buf) {
if (! result) {
current = result = new element_t;
if (! result.get()) {
result.reset(new element_t);
current = result.get();
} else {
current->next = new element_t;
current = current->next;
@ -158,7 +161,7 @@ element_t * format_t::parse_elements(const std::string& fmt)
current->chars = std::string(buf, q);
}
return result;
return result.release();
}
void format_t::format_elements(std::ostream& out,

View file

@ -55,7 +55,8 @@ bool journal_t::remove_entry(entry_t * entry)
entry_t * journal_t::derive_entry(strings_list::iterator i,
strings_list::iterator end) const
{
entry_t * added = new entry_t;
std::auto_ptr<entry_t> added(new entry_t);
entry_t * matching = NULL;
if (! parse_date((*i).c_str(), &added->date)) {
@ -97,17 +98,17 @@ entry_t * journal_t::derive_entry(strings_list::iterator i,
m_xact = matching->transactions.front();
amount_t amt(*i++);
first = xact = new transaction_t(added, m_xact->account, amt, amt);
first = xact = new transaction_t(added.get(), m_xact->account, amt, amt);
added->add_transaction(xact);
if (xact->amount.commodity->symbol.empty()) {
xact->amount.commodity = m_xact->amount.commodity;
xact->cost.commodity = m_xact->amount.commodity;
}
added->add_transaction(xact);
m_xact = matching->transactions.back();
xact = new transaction_t(added, m_xact->account,
xact = new transaction_t(added.get(), m_xact->account,
- first->amount, - first->amount);
added->add_transaction(xact);
@ -149,12 +150,11 @@ entry_t * journal_t::derive_entry(strings_list::iterator i,
}
amount_t amt(*i++);
transaction_t * xact = new transaction_t(added, acct, amt, amt);
transaction_t * xact = new transaction_t(added.get(), acct, amt, amt);
added->add_transaction(xact);
if (! xact->amount.commodity)
xact->amount.commodity = cmdty;
added->add_transaction(xact);
}
if (i != end && std::string(*i++) == "-from" && i != end) {
@ -169,12 +169,13 @@ entry_t * journal_t::derive_entry(strings_list::iterator i,
std::exit(1);
}
transaction_t * xact
= new transaction_t(added, matching->transactions.back()->account);
= new transaction_t(added.get(),
matching->transactions.back()->account);
added->add_transaction(xact);
}
}
return added;
return added.release();
}
int parse_journal_file(const std::string& path,

30
main.cc
View file

@ -374,8 +374,9 @@ int main(int argc, char * argv[], char * envp[])
// Setup local and global variables, depending on config settings.
std::auto_ptr<std::ostream> output_stream;
std::auto_ptr<interval_t> report_interval;
std::time_t interval_begin;
interval_t report_interval;
std::time_t interval_begin = 0;
if (config->download_quotes)
commodity_t::updater = new quotes_by_script(config->price_db,
@ -391,13 +392,12 @@ int main(int argc, char * argv[], char * envp[])
try {
std::istringstream stream(config->interval_text);
std::time_t begin = -1, end = -1;
report_interval.reset(interval_t::parse(stream, &begin, &end));
if (report_interval->seconds == 0 &&
report_interval->months == 0 &&
report_interval->years == 0)
report_interval.release();
report_interval = interval_t::parse(stream, &begin, &end);
if (begin != -1) {
interval_begin = begin;
if (! config->predicate.empty())
config->predicate += "&";
char buf[32];
@ -481,12 +481,6 @@ int main(int argc, char * argv[], char * envp[])
} else {
formatter.reset(new format_transactions(OUT(), format, nformat));
// sort_transactions will sort all the transactions it sees, based
// on the `sort_order' value expression.
if (sort_order.get())
formatter.reset(new sort_transactions(formatter.release(),
sort_order.get()));
// filter_transactions will only pass through transactions
// matching the `display_predicate'.
formatter.reset(new filter_transactions(formatter.release(),
@ -498,6 +492,12 @@ int main(int argc, char * argv[], char * envp[])
formatter.reset(new calc_transactions(formatter.release(),
config->show_inverted));
// sort_transactions will sort all the transactions it sees, based
// on the `sort_order' value expression.
if (sort_order.get())
formatter.reset(new sort_transactions(formatter.release(),
sort_order.get()));
// changed_value_transactions adds virtual transactions to the
// list to account for changes in market value of commodities,
// which otherwise would affect the running total unpredictably.
@ -524,9 +524,9 @@ int main(int argc, char * argv[], char * envp[])
// of the week.
if (config->show_subtotal)
formatter.reset(new subtotal_transactions(formatter.release()));
else if (report_interval.get())
else if (report_interval)
formatter.reset(new interval_transactions(formatter.release(),
*report_interval,
report_interval,
interval_begin));
else if (config->days_of_the_week)
formatter.reset(new dow_transactions(formatter.release()));

View file

@ -54,7 +54,7 @@ transaction_t * parse_transaction_text(char * line, account_t * account,
{
// The account will be determined later...
transaction_t * xact = new transaction_t(entry, NULL);
std::auto_ptr<transaction_t> xact(new transaction_t(entry, NULL));
// The call to `next_element' will skip past the account name,
// and return a pointer to the beginning of the amount. Once
@ -100,7 +100,7 @@ transaction_t * parse_transaction_text(char * line, account_t * account,
if (! xact->cost.commodity)
xact->cost.commodity = commodity_t::null_commodity;
return xact;
return xact.release();
}
transaction_t * parse_transaction(std::istream& in, account_t * account,
@ -220,7 +220,7 @@ namespace {
entry_t * parse_entry(std::istream& in, account_t * master)
{
entry_t * curr = new entry_t;
std::auto_ptr<entry_t> curr(new entry_t);
static char line[MAX_LINE + 1];
in.getline(line, MAX_LINE);
@ -267,7 +267,7 @@ entry_t * parse_entry(std::istream& in, account_t * master)
TIMER_START(entry_xacts);
while (! in.eof() && (in.peek() == ' ' || in.peek() == '\t'))
if (transaction_t * xact = parse_transaction(in, master, curr))
if (transaction_t * xact = parse_transaction(in, master, curr.get()))
curr->add_transaction(xact);
TIMER_STOP(entry_xacts);
@ -276,14 +276,12 @@ entry_t * parse_entry(std::istream& in, account_t * master)
TIMER_START(entry_finish);
if (curr->transactions.empty() || ! finalize_entry(curr)) {
delete curr;
return NULL;
}
if (curr->transactions.empty() || ! finalize_entry(curr.get()))
return NULL; // ~auto_ptr will delete curr
TIMER_STOP(entry_finish);
return curr;
return curr.release();
}
template <typename T>
@ -380,7 +378,7 @@ unsigned int parse_textual_journal(std::istream& in, journal_t * journal,
struct std::tm when;
if (strptime(date.c_str(), "%Y/%m/%d %H:%M:%S", &when)) {
entry_t * curr = new entry_t;
std::auto_ptr<entry_t> curr(new entry_t);
curr->date = std::mktime(&when);
curr->state = entry_t::CLEARED;
curr->code = "";
@ -394,11 +392,12 @@ unsigned int parse_textual_journal(std::istream& in, journal_t * journal,
time_commodity = amt.commodity;
transaction_t * xact
= new transaction_t(curr, last_account, amt, amt,
= new transaction_t(curr.get(), last_account, amt, amt,
TRANSACTION_VIRTUAL);
curr->add_transaction(xact);
if (! finalize_entry(curr) || ! journal->add_entry(curr))
if (! finalize_entry(curr.get()) ||
! journal->add_entry(curr.release()))
assert(0);
count++;

View file

@ -371,16 +371,16 @@ inline value_expr_t * parse_value_term(const char * p) {
value_expr_t * parse_value_term(std::istream& in)
{
value_expr_t * node = NULL;
std::auto_ptr<value_expr_t> node;
char c = peek_next_nonws(in);
if (std::isdigit(c)) {
static char buf[2048];
READ_INTO(in, buf, 2048, c, std::isdigit(c));
node = new value_expr_t(value_expr_t::CONSTANT_I);
node.reset(new value_expr_t(value_expr_t::CONSTANT_I));
node->constant_i = std::atol(buf);
return node;
return node.release();
}
else if (c == '{') {
static char buf[2048];
@ -391,72 +391,72 @@ value_expr_t * parse_value_term(std::istream& in)
else
throw value_expr_error("Missing '}'");
node = new value_expr_t(value_expr_t::CONSTANT_A);
node.reset(new value_expr_t(value_expr_t::CONSTANT_A));
node->constant_a.parse(buf);
return node;
return node.release();
}
in.get(c);
switch (c) {
// Basic terms
case 'N':
node = new value_expr_t(value_expr_t::CONSTANT_T);
node.reset(new value_expr_t(value_expr_t::CONSTANT_T));
node->constant_t = now;
break;
case 'a': node = new value_expr_t(value_expr_t::AMOUNT); break;
case 'c': node = new value_expr_t(value_expr_t::COST); break;
case 'd': node = new value_expr_t(value_expr_t::DATE); break;
case 'X': node = new value_expr_t(value_expr_t::CLEARED); break;
case 'R': node = new value_expr_t(value_expr_t::REAL); break;
case 'n': node = new value_expr_t(value_expr_t::INDEX); break;
case 'l': node = new value_expr_t(value_expr_t::DEPTH); break;
case 'B': node = new value_expr_t(value_expr_t::BALANCE); break;
case 'O': node = new value_expr_t(value_expr_t::TOTAL); break;
case 'C': node = new value_expr_t(value_expr_t::COST_TOTAL); break;
case 'a': node.reset(new value_expr_t(value_expr_t::AMOUNT)); break;
case 'c': node.reset(new value_expr_t(value_expr_t::COST)); break;
case 'd': node.reset(new value_expr_t(value_expr_t::DATE)); break;
case 'X': node.reset(new value_expr_t(value_expr_t::CLEARED)); break;
case 'R': node.reset(new value_expr_t(value_expr_t::REAL)); break;
case 'n': node.reset(new value_expr_t(value_expr_t::INDEX)); break;
case 'l': node.reset(new value_expr_t(value_expr_t::DEPTH)); break;
case 'B': node.reset(new value_expr_t(value_expr_t::BALANCE)); break;
case 'O': node.reset(new value_expr_t(value_expr_t::TOTAL)); break;
case 'C': node.reset(new value_expr_t(value_expr_t::COST_TOTAL)); break;
// Relating to format_t
case 't': node = new value_expr_t(value_expr_t::VALUE_EXPR); break;
case 'T': node = new value_expr_t(value_expr_t::TOTAL_EXPR); break;
case 't': node.reset(new value_expr_t(value_expr_t::VALUE_EXPR)); break;
case 'T': node.reset(new value_expr_t(value_expr_t::TOTAL_EXPR)); break;
// Compound terms
case 'v': node = parse_value_expr("P(a,d)"); break;
case 'V': node = parse_value_term("P(O,d)"); break;
case 'g': node = parse_value_expr("v-c"); break;
case 'G': node = parse_value_expr("V-C"); break;
case 'o': node = parse_value_expr("d-b"); break;
case 'w': node = parse_value_expr("e-d"); break;
case 'v': node.reset(parse_value_expr("P(a,d)")); break;
case 'V': node.reset(parse_value_term("P(O,d)")); break;
case 'g': node.reset(parse_value_expr("v-c")); break;
case 'G': node.reset(parse_value_expr("V-C")); break;
case 'o': node.reset(parse_value_expr("d-b")); break;
case 'w': node.reset(parse_value_expr("e-d")); break;
// Functions
case '-':
node = new value_expr_t(value_expr_t::F_NEG);
node.reset(new value_expr_t(value_expr_t::F_NEG));
node->left = parse_value_term(in);
break;
case 'A':
node = new value_expr_t(value_expr_t::F_ABS);
node.reset(new value_expr_t(value_expr_t::F_ABS));
node->left = parse_value_term(in);
break;
case 'S':
node = new value_expr_t(value_expr_t::F_STRIP);
node.reset(new value_expr_t(value_expr_t::F_STRIP));
node->left = parse_value_term(in);
break;
case 'M':
node = new value_expr_t(value_expr_t::F_ARITH_MEAN);
node.reset(new value_expr_t(value_expr_t::F_ARITH_MEAN));
node->left = parse_value_term(in);
break;
case 'D': {
node = new value_expr_t(value_expr_t::O_SUB);
node.reset(new value_expr_t(value_expr_t::O_SUB));
node->left = parse_value_term("a");
node->right = parse_value_term(in);
break;
}
case 'P':
node = new value_expr_t(value_expr_t::F_VALUE);
node.reset(new value_expr_t(value_expr_t::F_VALUE));
if (peek_next_nonws(in) == '(') {
in.get(c);
node->left = parse_value_expr(in);
@ -497,16 +497,16 @@ value_expr_t * parse_value_term(std::istream& in)
throw value_expr_error("Missing closing '/'");
in.get(c);
node = new value_expr_t(short_account_mask ?
node.reset(new value_expr_t(short_account_mask ?
value_expr_t::F_SHORT_ACCOUNT_MASK :
(payee_mask ? value_expr_t::F_PAYEE_MASK :
value_expr_t::F_ACCOUNT_MASK));
value_expr_t::F_ACCOUNT_MASK)));
node->mask = new mask_t(buf);
break;
}
case '(':
node = parse_value_expr(in);
node.reset(parse_value_expr(in));
if (peek_next_nonws(in) == ')')
in.get(c);
else
@ -520,7 +520,7 @@ value_expr_t * parse_value_term(std::istream& in)
throw value_expr_error("Missing ']'");
in.get(c);
node = new value_expr_t(value_expr_t::CONSTANT_T);
node.reset(new value_expr_t(value_expr_t::CONSTANT_T));
if (! parse_date(buf, &node->constant_t))
throw value_expr_error("Failed to parse date");
break;
@ -531,32 +531,30 @@ value_expr_t * parse_value_term(std::istream& in)
break;
}
return node;
return node.release();
}
value_expr_t * parse_mul_expr(std::istream& in)
{
value_expr_t * node = NULL;
std::auto_ptr<value_expr_t> node(parse_value_term(in));
node = parse_value_term(in);
if (node && ! in.eof()) {
if (node.get() && ! in.eof()) {
char c = peek_next_nonws(in);
while (c == '*' || c == '/') {
in.get(c);
switch (c) {
case '*': {
value_expr_t * prev = node;
node = new value_expr_t(value_expr_t::O_MUL);
node->left = prev;
std::auto_ptr<value_expr_t> prev(node.release());
node.reset(new value_expr_t(value_expr_t::O_MUL));
node->left = prev.release();
node->right = parse_value_term(in);
break;
}
case '/': {
value_expr_t * prev = node;
node = new value_expr_t(value_expr_t::O_DIV);
node->left = prev;
std::auto_ptr<value_expr_t> prev(node.release());
node.reset(new value_expr_t(value_expr_t::O_DIV));
node->left = prev.release();
node->right = parse_value_term(in);
break;
}
@ -565,32 +563,30 @@ value_expr_t * parse_mul_expr(std::istream& in)
}
}
return node;
return node.release();
}
value_expr_t * parse_add_expr(std::istream& in)
{
value_expr_t * node = NULL;
std::auto_ptr<value_expr_t> node(parse_mul_expr(in));
node = parse_mul_expr(in);
if (node && ! in.eof()) {
if (node.get() && ! in.eof()) {
char c = peek_next_nonws(in);
while (c == '+' || c == '-') {
in.get(c);
switch (c) {
case '+': {
value_expr_t * prev = node;
node = new value_expr_t(value_expr_t::O_ADD);
node->left = prev;
std::auto_ptr<value_expr_t> prev(node.release());
node.reset(new value_expr_t(value_expr_t::O_ADD));
node->left = prev.release();
node->right = parse_mul_expr(in);
break;
}
case '-': {
value_expr_t * prev = node;
node = new value_expr_t(value_expr_t::O_SUB);
node->left = prev;
std::auto_ptr<value_expr_t> prev(node.release());
node.reset(new value_expr_t(value_expr_t::O_SUB));
node->left = prev.release();
node->right = parse_mul_expr(in);
break;
}
@ -599,56 +595,56 @@ value_expr_t * parse_add_expr(std::istream& in)
}
}
return node;
return node.release();
}
value_expr_t * parse_logic_expr(std::istream& in)
{
value_expr_t * node = NULL;
std::auto_ptr<value_expr_t> node;
if (peek_next_nonws(in) == '!') {
char c;
in.get(c);
node = new value_expr_t(value_expr_t::O_NOT);
node.reset(new value_expr_t(value_expr_t::O_NOT));
node->left = parse_logic_expr(in);
return node;
return node.release();
}
node = parse_add_expr(in);
node.reset(parse_add_expr(in));
if (node && ! in.eof()) {
if (node.get() && ! in.eof()) {
char c = peek_next_nonws(in);
if (c == '=' || c == '<' || c == '>') {
in.get(c);
switch (c) {
case '=': {
value_expr_t * prev = node;
node = new value_expr_t(value_expr_t::O_EQ);
node->left = prev;
std::auto_ptr<value_expr_t> prev(node.release());
node.reset(new value_expr_t(value_expr_t::O_EQ));
node->left = prev.release();
node->right = parse_add_expr(in);
break;
}
case '<': {
value_expr_t * prev = node;
node = new value_expr_t(value_expr_t::O_LT);
std::auto_ptr<value_expr_t> prev(node.release());
node.reset(new value_expr_t(value_expr_t::O_LT));
if (peek_next_nonws(in) == '=') {
in.get(c);
node->kind = value_expr_t::O_LTE;
}
node->left = prev;
node->left = prev.release();
node->right = parse_add_expr(in);
break;
}
case '>': {
value_expr_t * prev = node;
node = new value_expr_t(value_expr_t::O_GT);
std::auto_ptr<value_expr_t> prev(node.release());
node.reset(new value_expr_t(value_expr_t::O_GT));
if (peek_next_nonws(in) == '=') {
in.get(c);
node->kind = value_expr_t::O_GTE;
}
node->left = prev;
node->left = prev.release();
node->right = parse_add_expr(in);
break;
}
@ -663,42 +659,40 @@ value_expr_t * parse_logic_expr(std::istream& in)
}
}
return node;
return node.release();
}
value_expr_t * parse_value_expr(std::istream& in)
{
value_expr_t * node = NULL;
std::auto_ptr<value_expr_t> node(parse_logic_expr(in));
node = parse_logic_expr(in);
if (node && ! in.eof()) {
if (node.get() && ! in.eof()) {
char c = peek_next_nonws(in);
while (c == '&' || c == '|' || c == '?') {
in.get(c);
switch (c) {
case '&': {
value_expr_t * prev = node;
node = new value_expr_t(value_expr_t::O_AND);
node->left = prev;
std::auto_ptr<value_expr_t> prev(node.release());
node.reset(new value_expr_t(value_expr_t::O_AND));
node->left = prev.release();
node->right = parse_logic_expr(in);
break;
}
case '|': {
value_expr_t * prev = node;
node = new value_expr_t(value_expr_t::O_OR);
node->left = prev;
std::auto_ptr<value_expr_t> prev(node.release());
node.reset(new value_expr_t(value_expr_t::O_OR));
node->left = prev.release();
node->right = parse_logic_expr(in);
break;
}
case '?': {
value_expr_t * prev = node;
node = new value_expr_t(value_expr_t::O_QUES);
node->left = prev;
value_expr_t * choices = new value_expr_t(value_expr_t::O_COL);
node->right = choices;
std::auto_ptr<value_expr_t> prev(node.release());
node.reset(new value_expr_t(value_expr_t::O_QUES));
node->left = prev.release();
value_expr_t * choices;
node->right = choices = new value_expr_t(value_expr_t::O_COL);
choices->left = parse_logic_expr(in);
c = peek_next_nonws(in);
if (c != ':') {
@ -722,7 +716,7 @@ value_expr_t * parse_value_expr(std::istream& in)
}
}
return node;
return node.release();
}
#ifdef DEBUG_ENABLED

View file

@ -90,12 +90,11 @@ void changed_value_transactions::operator()(transaction_t * xact)
if (balance_t diff = cur_bal - prev_bal) {
entry_t * entry = new entry_t;
entry_temps.push_back(entry);
entry->payee = "Commodities revalued";
entry->date = current;
entry_temps.push_back(entry);
for (amounts_map::const_iterator i = diff.amounts.begin();
i != diff.amounts.end();
i++) {
@ -138,10 +137,10 @@ void subtotal_transactions::flush(const char * spec_fmt)
}
entry_t * entry = new entry_t;
entry->payee = buf;
entry_temps.push_back(entry);
entry->payee = buf;
for (balances_map::iterator i = balances.begin();
i != balances.end();
i++) {