views:

155

answers:

3

I have a method as follows (from a class than implements TBB task interface - not currently multithreading though) My problem is that two ways of accessing a vector are causing quite different behaviour - one works and the other causes the entire program to bomb out quite spectacularly (this is a plugin and normally a crash will be caught by the host - but this one takes out the host program as well! As I said quite spectacular)

void PtBranchAndBoundIterationOriginRunner::runOrigin(int origin, int time) const // NOTE: const method
{
    BOOST_FOREACH(int accessMode, m_props->GetAccessModes())
    {
        // get a const reference to appropriate vector from member variable
        // map<int, vector<double>> m_rowTotalsByAccessMode;
        const vector<double>& rowTotalsForAccessMode = m_rowTotalsByAccessMode.find(accessMode)->second;

        if (origin != 129) continue; // Additional debug constrain: I know that the vector only has one non-zero element at index 129

        m_job->Write("size: " + ToString(rowTotalsForAccessMode.size()));
        try {
            // check for early return... i.e. nothing to do for this origin 
            if (!rowTotalsForAccessMode[origin])    continue; // <- this works
            if (!rowTotalsForAccessMode.at(origin)) continue; // <- this crashes
        } catch (...) {
            m_job->Write("Caught an exception"); // but its not an exception
        }

        // do some other stuff
    }
}

I hate not putting in well defined questions but at the moment my best phrasing is : "WTF?"

I'm compiling this with Intel C++ 11.0.074 [IA-32] using Microsoft (R) Visual Studio Version 9.0.21022.8 and my implementation of vector has

const_reference operator[](size_type _Pos) const
{   // subscript nonmutable sequence

#if _HAS_ITERATOR_DEBUGGING
    if (size() <= _Pos)
    {
        _DEBUG_ERROR("vector subscript out of range");
        _SCL_SECURE_OUT_OF_RANGE;
    }
#endif /* _HAS_ITERATOR_DEBUGGING */
    _SCL_SECURE_VALIDATE_RANGE(_Pos < size());

    return (*(_Myfirst + _Pos));
}

(Iterator debugging is off - I'm pretty sure) and

const_reference at(size_type _Pos) const
{   // subscript nonmutable sequence with checking
    if (size() <= _Pos)
        _Xran();
    return (*(begin() + _Pos));
}

So the only difference I can see is that at calls begin instead of simply using _Myfirst - but how could that possibly be causing such a huge difference in behaviour?

UPDATE:

The index is within range - the size is printed out as 377 and the index is constrained to 129.

The member variable has an entry corresponding to accessMode

The entire thing has been wrapped in the following to clarify @nikko suggestion:

map<int, vector<double>>::const_iterator it = m_rowTotalsByAccessMode.find(accessMode);
if (it != m_rowTotalsByAccessMode.end())
{
    ...

UPDATE I've upgraded my compiler to the latest version 11.1.065 and this is no longer happening. Looks like it was weirdness somewhere.

+3  A: 

I did not see where you checked that rowTotalsForAccessMode was valid. Maybe your "m_rowTotalsByAccessMode.find(accessMode)" does not work.

You should check the result of your .find() against iterator end() to see if it's valid

Nikko
+1 I think the OP will eventually find out that the `[]`-version not crashing is a fluke.
Andreas Brinck
Good point nikko, but for the purposes of the question, it has been found... I populate it explicitly
Jamie Cook
+1 to Nikko, these two scratched my eye as well. So actually the problem exists in both scenarios, it's just that the one with '[]' silently does ABW and the one with 'at()' throws. The uncaugt exception is causing program to "abort" on *nix, not sure how it maps to MS though.
bobah
@bobah: But there is `catch(...)` which should catch the exception unless this code is getting executed in a stack unwinding process.
Naveen
@bobah: except that it's not an exception at the at call point... it's a god-awful coredump.... but you are right - if .find() returns end() then I attempt to deference the end pointer that would put things into a pretty bad state.
Jamie Cook
@Naveen - yes, right, missed it, so it's not out of range exception.
bobah
A: 

Can't you single step the program in a debugger (into at) and see what is causing the crash? There are two options:

  1. rowTotalsForAccessMode is invalid
  2. origin is out of range
Andreas Brinck
sorry... only occurs in release mode.
Jamie Cook
You should be able to single step in release as well, no?
Andreas Brinck
Visual Studio does some weird jumping around in Release mode.. I have no examples, but if memory serves me right (hehe), I usually saw it when I had memory corruption (which I guess debug mode compensates for?)
Default
No, that's not it. The debugger does jump around a bit in release mode but it's because the optimizations may have moved/removed/inlined/unrolled code etc. This doesn't stop you from single stepping into functions though and finding the point of the crash.
Andreas Brinck
Most likely all the standard library code is inlined though. I'm not sure how well the debugger would handle that
Mark B
It depends, the standard library code doesn't get any special treatment, it will be inlined to the same extent as all other code. If you have a complicated function in the standard library it most certainly won't be inlined.
Andreas Brinck
A: 

I hate answering my own questions but this seems to be a situation where it is required. As it says in the update, I downloaded and installed the latest intel c++ compiler and recompiled from scratch which seems to have fixed the problem. I've also rebuilt the entire project from scratch using the 11.0.074 compiler to rule out a corruption of one of the binaries; even a clean build results in the crash!

I'm going to follow this up on the Intel forums, thanks to everyone who put in some time and effort to this problem.

Jamie Cook