lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] _M_range_check fails when running "new" PDF


From: Greg Chicares
Subject: Re: [lmi] _M_range_check fails when running "new" PDF
Date: Wed, 14 Feb 2018 00:38:33 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.2

On 2018-02-13 23:07, Vadim Zeitlin wrote:
> On Tue, 13 Feb 2018 20:45:59 +0000 Greg Chicares <address@hidden> wrote:
> 
> GC> We see this message:
> GC>   vector::_M_range_check: __n (which is 0) >= this->size() (which is 0)
> GC> with ledger type mce_individual_private_placement when we run an
> GC> "inforce" illustration. "Inforce" means, e.g., that you bought a
> GC> life insurance policy in the past, and now you want an illustration
> GC> that starts today (as opposed to starting when the policy was sold).
> 
>  Thanks for finding this bug, I could reproduce it easily, but couldn't see
> where did the check fail exactly as gdb refused to "catch throw" or stop at
> stl_vector.h:804, where this exception was thrown. I still have no idea how
> exactly to debug standard library code under MinGW, but I could see the
> same problem in the native Linux build of the program (where I had to fix a
> couple of problems to be able to use configure again, hence my recent
> changes to it and Makefile.am) and now I know what happens:

This is yet another reason why I should change lmi's makefiles to build
{64, 32}-bit {GNU/Linux, msw} binaries. But there's no time for that now,
so maybe I should use automake to build 64-bit GNU/Linux binaries for
the time being, because I do know a little about gdb, but debugging msw
binaries in 'wine' seems hopeless after lots of fruitless effort. Anyway...

>  The problem is due to "IrrCsv_GuaranteedZero" vector being empty in this

Oh. That thing.

// TODO ?? It is extraordinary that this "invariant" class uses and
// even sets some data that vary by basis and therefore seem to belong
// in the complementary "variant" class.

> case, which is unexpected as the table generation code assumes that all the
> values do always exist. A trivial fix for the problem would be to check
> that the index is valid in ledger_evaluator::operator() and return an empty
> string if it isn't, but I'm not really comfortable with doing this, as this
> could easily hide genuine errors too.

Agreed.

>  Another possibility would be to add a separate ledger_evaluator method
> called get_if_exists_or_empty() or something shorter but with the same
> connotation, that could be explicitly used when the caller expects that the
> value might not be available. But while this is better than never checking
> for the vector size at all, it's still potentially dangerous.

Agreed.

>  So my preferred solution would be to fill IrrCsv_GuaranteedZero (and other
> similar vectors) with zeroes when LedgerInvariant::IrrCsvGuar0 (and others)
> is empty. What do you think of this proposal?

I think it sounds good. Instead of zero, I'd like to fill it with negative
one, i.e., -100%, which is a better default: a stream of payments and
benefits can easily have a negative IRR, so we don't want to call it zero
because that could easily make this column better than reality, which is
An Extremely Bad Thing. But I can confidently promise an IRR of at least
-100% in every situation, because that means you lose all your money
immediately, and that's the worst that can happen in the life insurance
business.

I imagine that the fix is something like:

    // Calculate these IRRs only for ledger types that actually use a
    // basis with a zero percent separate-account rate. This is a
    // matter not of efficiency but of validity: values for unused
    // bases are not dependably initialized.
    //
    // This calculation should be distributed among the variant
    // ledgers, so that it gets run for every basis actually used.
    if
        (0 == std::count
            (LedgerValues.GetRunBases().begin()
            ,LedgerValues.GetRunBases().end()
            ,mce_run_gen_curr_sep_zero
            // Proxy for mce_run_gen_guar_sep_zero too.
            )
        )
        {
+       IrrCsvGuar0 = std::vector(the_appropriate_length, -1);
+       IrrDbGuar0  = likewise
+       IrrCsvCurr0 = likewise
+       IrrDbCurr0  = likewise
        return;
        }

but let me sleep on it--I'll give you an answer in the morning.

>  Also, would you know of any other vectors used for table columns which
> might not have the values for all (or any, as is the case here) years?

Not off the top of my head, but I'll take a look tomorrow.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]