views:

2213

answers:

9

I have a vector that contains POSITIONs. When I try to push_back or clear, the program crashes. The callstack shows _invalid_parameter_noinfo in one of the frames. I googled and found a solution(defining _HAS_ITERA.... and _SECURE_SCL to 0) , but was not effective. I'm using VS2008 with MFC feature pack installed on vista.

Please help. Thanks

+3  A: 

In an otherwise correct program, a push_back() should never cause a crash. So I'm guessing that the problem isn't with the vector, but somewhere else in your code. Probably memory is getting corrupted through by writing through an invalid pointer, past the end of an array, double deleting a pointer, or something similar. It just doesn't have any noticeable effects until you access the vector.

KeithB
A: 

The call stack:

Desktop.exe!_crt_debugger_hook(int _Reserved=0) Line 65 C
Desktop.exe!_invalid_parameter(const wchar_t * pszExpression=0x00000000, const wchar_t * pszFunction=0x00000000, const wchar_t * pszFile=0x00000000, unsigned int nLine=0, unsigned int pReserved=0) Line 112 + 0x7 bytes C++
Desktop.exe!_invalid_parameter_noinfo() Line 125 + 0xc bytes C++
Desktop.exe!std::vector >::insert(std::_Vector_const_iterator > _Where=..., CRecord * const & _Val=0x01703200) Line 878 + 0x1e bytes C++
Desktop.exe!COutlineTextView::prepareSelBounds() Line 4816 C++
Desktop.exe!COutlineTextView::OnMouseMove(unsigned int nFlags=1, CPoint point={...}) Line 167 + 0x40 bytes C++
Desktop.exe!COutlineEditView::OnMouseMove(unsigned int nFlags=1, CPoint pointMove={...}) Line 2935 C++
Desktop.exe!CWnd::OnWndMsg(unsigned int message=512, unsigned int wParam=1, long lParam=3231936, long * pResult=0x007bfc9c) Line 2062 C++

Code snippet where it crashes:

declared as
std::vector<POSITION> m_selection;

in member function: prepareSelBounds

if (m_selection.size() > 0){

m_selection.clear(); // previously used to crash here.       
}                    // then I put this if




.........
...........

POSITION pos = m_selStart.getItem();


while(pos != NULL && pos != m_selEnd.getItem())

{
m_selection.push_back(pos); // CRASH HERE

pos = getMan()->getNext(pos);
}

ASSERT(pos);

m_selection.push_back(m_selEnd.getItem());
A: 

Crashes do not always happen where the error is. If you have a bad pointer or overflow a buffer you could write over a part of the stack or heap that the vector uses. This would cause incorrect data inside the std::vector causing invariants to be violated and a crash.

On Linux the solution is Valgrind for user space apps since that informs you of every bad memory write. I am not too sure besides randomly playing with your code of what to do on Windows.

Ed
+1  A: 

Thanks for the code but you did NOT provide any of the usfull bits!

We need to know how POSITION is defined.
Specifically does it contain any RAW pointers.

What are:

  • m_selStart
  • m_selEnd

How are they defined where do they come from?

In C++ End usually indicates an element one past the end of a container. De-referencing ot (in any way) is not a good idea. Thus this line looks very suspicious.

 m_selection.push_back(m_selEnd.getItem());
Martin York
A: 

I'm not sure what the reference about _SECURE_SCL_ you found said, but I've had really crazy and hard to debug problems when linking code having different values for this variable and the results are very similar to the ones you describe.

What I guess happen is that the stl libraries symbols look identical regardless of what _SECURE_SCL_ is defined to. However some data structure sizes or other important things seems to change. Since stl code tends to be inlined, duplicate symbols may be present during linking. When the compiler decide not to inline a function call the linker can choose any of the versions it finds and if it happens to use the one where _SECURE_SCL_ has a different value than yours you get random crashes in situations like the one you described.

And, yes I've seen libraries distributed as static libraries (as opposed to source code) causing my code to crash because of this.

So if you find no more reasonable explanation for your crash, make sure the variable is set to the same value in all libraries you use that uses stl.

This might not be the cause of your problem, but it's really one of the most annoying and hard to debug problems I've run into in a long time so when you gave me a post to whine about it, I couldn't restrain myself :)

Good luck

Laserallan
A: 
Desktop.exe!COutlineTextView::OnMouseMove(unsigned int nFlags=1, CPoint point={...}) Line 167 + 0x40 bytes C++

yikes - you're not adding the selected items in a ListCtrl to your vector everytime the mouse moves are you?!

You still haven't given us enough code - are you removing from the vector in a different thread? What is a POSITION? Is it a long typedef, or something else that's more obscure, I notice the insert mentions CRecord* in the callstack.

gbjbaanb
+1  A: 

First thing to try is to remove whatever settings you're doing with _HAS_ITERATOR_DEBUGGING and _SECURE_SCL. In my experience, this is the #1 source of mysterious crashes with STL containers with Microsoft's implementation.

If you're using any static library that uses a different setting for either of those macros, you'll have a binary incompatibility issue that will crash you, and it won't be detected at compile or link time.

Tom
A: 

Here is more of the code:

class CCursorPos
{
public:

    CCursorPos()
    {
     invalidate();
    }

    CCursorPos(const CCursorPos& pos)
    {
     *this = pos;
    }

    BOOL isValid() const
    {
     return (m_posItem!=NULL && m_textPos.x > -1 && m_textPos.y > -1);
    }

    CCursorPos& operator=(const CCursorPos& pos)
    {
     ASSERT(pos.isValid());
     setCursor(pos.getItem(),pos.getTextPoint());
     return *this;
    }

    BOOL operator==(const CCursorPos& pos) const
    {
     ASSERT(isValid());
     ASSERT(pos.isValid());

     return (getItem() == pos.getItem() && 
      getTextPoint() == pos.getTextPoint());
    }

    BOOL operator!=(const CCursorPos& pos) const
    {
     return !(*this == pos);
    }

    POSITION getItem() const
    {
     ASSERT(isValid());
     return m_posItem;
    }

    const CPoint& getTextPoint() const
    {
     ASSERT(isValid());
     return m_textPos;
    }

    void invalidate()
    {
     m_textPos.x = m_textPos.y = -1;
     m_posItem = NULL;
    }

    void setCursor(const POSITION& pos, const CPoint& ptText)
    {
     m_textPos = ptText;
     m_posItem = pos;
     ASSERT(isValid());
    }

protected:

    CPoint m_textPos;  // in view coordinates
    POSITION m_posItem;
};

........

class COutlineTextView
{
.....
CCursorPos m_selStart, m_selEnd;
std::vector m_selection;

....
};

void COutlineTextView::prepareSelBounds()
{
      if (m_selection.size() > 0){
     m_selection.clear();  // Stoppped crashing here since I put it within if ().
    }

       .....

    POSITION pos = m_selStart.getItem();
    while(pos != NULL && pos != m_selEnd.getItem())
    {
     m_selection.push_back(pos);             // CRASH HERE on first iteration
     pos = getOutline()->getNext(pos);
    }

    ASSERT(pos);
    m_selection.push_back(m_selEnd.getItem());
       ...
}
Ron
A: 

if your std::vector is a member of a class, make sure that you're not using ZeroMemory or something similiar with it. I've used it and my program crashes in release mode. However, it works fine in debug mode. The program works fine in release and debug mode if i don't use ZeroMemory.

xnacks