Last active
October 22, 2017 18:59
-
-
Save jralls/acc9f8db275b6b74c5b30908aeca0119 to your computer and use it in GitHub Desktop.
Backtrace of GncNumeric abort
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Thread 1 hit Breakpoint 1, 0x76e2b28b in msvcrt!abort () | |
from C:\WINDOWS\System32\msvcrt.dll | |
(gdb) bt | |
#0 0x76e2b28b in msvcrt!abort () from C:\WINDOWS\System32\msvcrt.dll | |
#1 0x67f8ed0a in uw_init_context_1 () | |
from C:\gcdev64\gnucash\unstable\build\gnucash-git\bin\libgnc-core-utils.dll | |
#2 0x67f8f50d in _Unwind_Resume () | |
from C:\gcdev64\gnucash\unstable\build\gnucash-git\bin\libgnc-core-utils.dll | |
#3 0x00403691 in GncNumeric::GncNumeric (this=0x83fdd8, str=..., | |
autoround=false) | |
at C:/gcdev64/gnucash/unstable/src/gnucash-git/libgnucash/engine/gnc-numeric.cpp:137 | |
#4 0x00408787 in GncNumeric::numeric_from_string (this=0x83fe38, | |
str=0x83fe8b "-1/0", n=0x83fe78) | |
at C:/gcdev64/gnucash/unstable/src/gnucash-git/libgnucash/engine/gnc-numeric.cpp:1217 | |
#5 0x00408943 in string_to_gnc_numeric (str=0x83fe8b "-1/0", n=0x83fe78) | |
at C:/gcdev64/gnucash/unstable/src/gnucash-git/libgnucash/engine/gnc-numeric.cpp:1239 | |
#6 0x00410881 in check_gnc_throw () | |
at C:/gcdev64/gnucash/unstable/src/gnucash-git/libgnucash/engine/test/test-numeric.cpp:115 | |
#7 0x004187f1 in run_test () | |
at C:/gcdev64/gnucash/unstable/src/gnucash-git/libgnucash/engine/test/test-numeric.cpp:907 | |
#8 0x00418844 in main (argc=1, argv=0x2d1e3a8) | |
at C:/gcdev64/gnucash/unstable/src/gnucash-git/libgnucash/engine/test/test-numeric.cpp:925 | |
(gdb) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 68ab5ae680d52b677696384377bfe63b13be0360 Mon Sep 17 00:00:00 2001 | |
From: John Ralls <jralls@ceridwen.us> | |
Date: Sun, 22 Oct 2017 11:52:42 -0700 | |
Subject: [PATCH] Exception experiments. | |
--- | |
libgnucash/engine/gnc-numeric.cpp | 178 ++++++++++++++++++-------------- | |
libgnucash/engine/gnc-numeric.hpp | 3 + | |
libgnucash/engine/test/test-numeric.cpp | 15 +++ | |
3 files changed, 118 insertions(+), 78 deletions(-) | |
diff --git a/libgnucash/engine/gnc-numeric.cpp b/libgnucash/engine/gnc-numeric.cpp | |
index 0b7770a..e16092e 100644 | |
--- a/libgnucash/engine/gnc-numeric.cpp | |
+++ b/libgnucash/engine/gnc-numeric.cpp | |
@@ -141,80 +141,87 @@ GncNumeric::GncNumeric(const std::string& str, bool autoround) | |
*/ | |
if (str.empty()) | |
throw std::invalid_argument("Can't construct a GncNumeric from an empty string."); | |
- if (regex_search(str, m, hex_rational)) | |
- { | |
- GncNumeric n(stoll(m[1].str(), nullptr, 16), | |
- stoll(m[2].str(), nullptr, 16)); | |
- m_num = n.num(); | |
- m_den = n.denom(); | |
- return; | |
- } | |
- if (regex_search(str, m, hex_over_num)) | |
- { | |
- GncNumeric n(stoll(m[1].str(), nullptr, 16), | |
- stoll(m[2].str())); | |
- m_num = n.num(); | |
- m_den = n.denom(); | |
- return; | |
- } | |
- if (regex_search(str, m, num_over_hex)) | |
- { | |
- GncNumeric n(stoll(m[1].str()), | |
- stoll(m[2].str(), nullptr, 16)); | |
- m_num = n.num(); | |
- m_den = n.denom(); | |
- return; | |
- } | |
- if (regex_search(str, m, numeral_rational)) | |
- { | |
- GncNumeric n(stoll(m[1].str()), stoll(m[2].str())); | |
- m_num = n.num(); | |
- m_den = n.denom(); | |
- return; | |
- } | |
- if (regex_search(str, m, decimal)) | |
- { | |
- GncInt128 high(stoll(m[1].str())); | |
- GncInt128 low(stoll(m[2].str())); | |
- int64_t d = powten(m[2].str().length()); | |
- GncInt128 n = high * d + (high > 0 ? low : -low); | |
- if (!autoround && n.isBig()) | |
- { | |
- std::ostringstream errmsg; | |
- errmsg << "Decimal string " << m[1].str() << "." << m[2].str() | |
- << "can't be represented in a GncNumeric without rounding."; | |
- throw std::overflow_error(errmsg.str()); | |
- } | |
- while (n.isBig() && d > 0) | |
- { | |
- n >>= 1; | |
- d >>= 1; | |
- } | |
- if (n.isBig()) //Shouldn't happen, of course | |
- { | |
- std::ostringstream errmsg; | |
- errmsg << "Decimal string " << m[1].str() << "." << m[2].str() | |
- << " can't be represented in a GncNumeric, even after reducing denom to " << d; | |
- throw std::overflow_error(errmsg.str()); | |
- } | |
- GncNumeric gncn(static_cast<int64_t>(n), d); | |
- m_num = gncn.num(); | |
- m_den = gncn.denom(); | |
- return; | |
- } | |
- if (regex_search(str, m, hex)) | |
- { | |
- GncNumeric n(stoll(m[1].str(), nullptr, 16),INT64_C(1)); | |
- m_num = n.num(); | |
- m_den = n.denom(); | |
- return; | |
- } | |
- if (regex_search(str, m, numeral)) | |
+ try | |
{ | |
- GncNumeric n(stoll(m[1].str()), INT64_C(1)); | |
- m_num = n.num(); | |
- m_den = n.denom(); | |
- return; | |
+ if (regex_search(str, m, hex_rational)) | |
+ { | |
+ GncNumeric n(stoll(m[1].str(), nullptr, 16), | |
+ stoll(m[2].str(), nullptr, 16)); | |
+ m_num = n.num(); | |
+ m_den = n.denom(); | |
+ return; | |
+ } | |
+ if (regex_search(str, m, hex_over_num)) | |
+ { | |
+ GncNumeric n(stoll(m[1].str(), nullptr, 16), | |
+ stoll(m[2].str())); | |
+ m_num = n.num(); | |
+ m_den = n.denom(); | |
+ return; | |
+ } | |
+ if (regex_search(str, m, num_over_hex)) | |
+ { | |
+ GncNumeric n(stoll(m[1].str()), | |
+ stoll(m[2].str(), nullptr, 16)); | |
+ m_num = n.num(); | |
+ m_den = n.denom(); | |
+ return; | |
+ } | |
+ if (regex_search(str, m, numeral_rational)) | |
+ { | |
+ GncNumeric n(stoll(m[1].str()), stoll(m[2].str())); | |
+ m_num = n.num(); | |
+ m_den = n.denom(); | |
+ return; | |
+ } | |
+ if (regex_search(str, m, decimal)) | |
+ { | |
+ GncInt128 high(stoll(m[1].str())); | |
+ GncInt128 low(stoll(m[2].str())); | |
+ int64_t d = powten(m[2].str().length()); | |
+ GncInt128 n = high * d + (high > 0 ? low : -low); | |
+ if (!autoround && n.isBig()) | |
+ { | |
+ std::ostringstream errmsg; | |
+ errmsg << "Decimal string " << m[1].str() << "." << m[2].str() | |
+ << "can't be represented in a GncNumeric without rounding."; | |
+ throw std::overflow_error(errmsg.str()); | |
+ } | |
+ while (n.isBig() && d > 0) | |
+ { | |
+ n >>= 1; | |
+ d >>= 1; | |
+ } | |
+ if (n.isBig()) //Shouldn't happen, of course | |
+ { | |
+ std::ostringstream errmsg; | |
+ errmsg << "Decimal string " << m[1].str() << "." << m[2].str() | |
+ << " can't be represented in a GncNumeric, even after reducing denom to " << d; | |
+ throw std::overflow_error(errmsg.str()); | |
+ } | |
+ GncNumeric gncn(static_cast<int64_t>(n), d); | |
+ m_num = gncn.num(); | |
+ m_den = gncn.denom(); | |
+ return; | |
+ } | |
+ if (regex_search(str, m, hex)) | |
+ { | |
+ GncNumeric n(stoll(m[1].str(), nullptr, 16),INT64_C(1)); | |
+ m_num = n.num(); | |
+ m_den = n.denom(); | |
+ return; | |
+ } | |
+ if (regex_search(str, m, numeral)) | |
+ { | |
+ GncNumeric n(stoll(m[1].str()), INT64_C(1)); | |
+ m_num = n.num(); | |
+ m_den = n.denom(); | |
+ return; | |
+ } | |
+ } | |
+ catch (std::invalid_argument& err) | |
+ { | |
+ throw; | |
} | |
std::ostringstream errmsg; | |
errmsg << "String " << str << " contains no recognizable numeric value."; | |
@@ -1202,22 +1209,37 @@ gnc_num_dbg_to_string(gnc_numeric n) | |
return p; | |
} | |
-gboolean | |
-string_to_gnc_numeric(const gchar* str, gnc_numeric *n) | |
+bool | |
+GncNumeric::numeric_from_string (const char* str, gnc_numeric *n) noexcept | |
{ | |
try | |
{ | |
GncNumeric an(str); | |
*n = static_cast<gnc_numeric>(an); | |
- return TRUE; | |
+ return true; | |
} | |
- catch (const std::exception& err) | |
+ catch (std::invalid_argument& err) | |
{ | |
PWARN("%s", err.what()); | |
- return FALSE; | |
+ return false; | |
+ } | |
+ catch (std::overflow_error& err) | |
+ { | |
+ PWARN("%s", err.what()); | |
+ return false; | |
} | |
} | |
+gboolean | |
+string_to_gnc_numeric(const gchar* str, gnc_numeric *n) | |
+{ | |
+ if (g_strcmp0(str, "-1/0") == 0) | |
+ PERR("Error Value in string!"); | |
+ GncNumeric numeric; | |
+ bool result = numeric.numeric_from_string(str, n); | |
+ return result ? TRUE : FALSE; | |
+} | |
+ | |
/* ******************************************************************* | |
* GValue handling | |
********************************************************************/ | |
diff --git a/libgnucash/engine/gnc-numeric.hpp b/libgnucash/engine/gnc-numeric.hpp | |
index d9ff3d7..49d065f 100644 | |
--- a/libgnucash/engine/gnc-numeric.hpp | |
+++ b/libgnucash/engine/gnc-numeric.hpp | |
@@ -228,6 +228,9 @@ public: | |
* details. | |
*/ | |
std::string to_string() const noexcept; | |
+ /** Fill a GncNumeric from a string | |
+ */ | |
+ bool numeric_from_string (const char* str, gnc_numeric *n) noexcept; | |
/** | |
* @return true if the denominator is a power of ten, false otherwise. | |
*/ | |
diff --git a/libgnucash/engine/test/test-numeric.cpp b/libgnucash/engine/test/test-numeric.cpp | |
index 2f284f7..7617c74 100644 | |
--- a/libgnucash/engine/test/test-numeric.cpp | |
+++ b/libgnucash/engine/test/test-numeric.cpp | |
@@ -27,6 +27,7 @@ extern "C" | |
#include "config.h" | |
#include <ctype.h> | |
#include <glib.h> | |
+#include <glib/gprintf.h> | |
#include "cashobjects.h" | |
#include "test-stuff.h" | |
#include "test-engine-stuff.h" | |
@@ -106,6 +107,19 @@ check_binary_op_r (gnc_numeric expected, | |
g_free (str); | |
} | |
+static void | |
+check_gnc_throw (void) | |
+{ | |
+ const char str[] = "-1/0"; | |
+ gnc_numeric n; | |
+ if (string_to_gnc_numeric(str, &n)) | |
+ { | |
+ g_printf ("Well, it didn't abort, but it also succeeded.\n"); | |
+ return; | |
+ } | |
+ g_printf ("Creation correctly failed.\n"); | |
+} | |
+ | |
/* ======================================================= */ | |
static gboolean | |
@@ -890,6 +904,7 @@ check_mult_div (void) | |
static void | |
run_test (void) | |
{ | |
+ check_gnc_throw (); | |
check_eq_operator (); | |
check_reduce (); | |
check_equality_operator (); | |
-- | |
1.9.4.msysgit.0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment