none
Weird crash in c++ maps.find() when compiled in Release mode

    Question

  • Hi,

    I am seeing a weird crash only when the following piece of code is compiled in release mode.

    typedef map<unsigned int, ContextStructureX *> keyContextMap;

    void functionX(unsigned int key)

    {

    keyContextMap::iterator itr;

    itr = keyContextMap.find(key)   <<<<<<---- Crash seen here..

    if (itr == keyContextMap.end())

    {

         // Do something

    }

    }

    Backtrace points to the crash in lower_bound function call:

    iterator find(const key_type& _KeyVal)

    {

    iterator _Where = lower_bound(_Keyval);     <<<<<<---- Crash here

    }

    Friday, March 22, 2013 8:43 AM

Answers

  • There are a few things that happen differently in release mode that can cause such things.   All reflect some other defect in your code. 

    For instance, the memory allocation in debug mode places unused space around each allocation filled with a pattern (so it can be used to detect such problem) where everything gets tightly packed without padding in Release mode.

    In debug mode, memory that isn't supposed to be initialized also gets initialized with a distinctive pattern.   Sometimes that pattern can cause different code paths than the value that just coincidentally resides in the uninitialized storage in release mode (often I find zeros in release mode rather than the cdcdcdcd, for instance).

    I'd be looking ELSEWHERE in your code.

    Friday, March 22, 2013 12:21 PM

All replies

  • >I am seeing a weird crash only when the following piece of code is compiled in release mode.

    Which compiler?

    Do you have a stand-alone console application that can reproduce it?

    What compiler settings have you used - does changing the optimisation
    settings make any difference?

    Dave

    Friday, March 22, 2013 9:00 AM
  • There are a few things that happen differently in release mode that can cause such things.   All reflect some other defect in your code. 

    For instance, the memory allocation in debug mode places unused space around each allocation filled with a pattern (so it can be used to detect such problem) where everything gets tightly packed without padding in Release mode.

    In debug mode, memory that isn't supposed to be initialized also gets initialized with a distinctive pattern.   Sometimes that pattern can cause different code paths than the value that just coincidentally resides in the uninitialized storage in release mode (often I find zeros in release mode rather than the cdcdcdcd, for instance).

    I'd be looking ELSEWHERE in your code.

    Friday, March 22, 2013 12:21 PM
  • I am using VC++ compiler from Visual Studio 2008.

    On the release mode the optimization is set to /O2 while in debug mode, optimization is turned off.  The problem is seen only with optimization set to O2 (Release mode).  I do not have a standalone piece of code that can reproduce it and unfortunately, the piece of code is a fraction of tonnes of code forming the application.

    This piece of code under problem is multi thread safe and the map itself is accessible to a single thread at any point of time.

    Visual Studio alerts that its a access violation.

    Friday, March 22, 2013 1:22 PM
  • I am using VC++ compiler from Visual Studio 2008.

    On the release mode the optimization is set to /O2 while in debug mode, optimization is turned off.  The problem is seen only with optimization set to O2 (Release mode).  I do not have a standalone piece of code that can reproduce it and unfortunately, the piece of code is a fraction of tonnes of code forming the application.

    Try /O1 (minimize size) - it's often the best option to choose anyway.

    Without a reasonably simple repro project that you can share, it'll be
    difficult to progress this.

    Dave

    Friday, March 22, 2013 2:10 PM
  • I can see you forget to  check whether map is empty or not . Before performing your operation.Most Probably that's the reason of your crash.

    Thanks


    Rupesh Shukla


    Friday, March 22, 2013 4:13 PM
  • In those cases where the map is empty, couldn't I expect maps.find() to return maps.end?
    Friday, March 22, 2013 5:59 PM
  • Yes you can. 


    Friday, March 22, 2013 6:24 PM
  • Although it has no exception specification, 'find' usually does not throw by itself. The reason there is no exception specification is that 'find' uses the comparison function for keys, that may throw.So it's good to check for empty before performing any operation.

    Thanks


    Rupesh Shukla

    Friday, March 22, 2013 6:44 PM
  • The comparison function for unsigned is NOT going to throw.    Further, if the map is empty, the comparison operator won't be called.  What's there to compare?    It is 100% safe to run find() on an empty map.

    Since we have a map of an unsigned first and a pointer second, it's unlikely that there's any issue with the contents of the map.   The problem most likely is that someone either corrupted the map or free store outside of this.

    If the poster could provide more of the program that fails, we can try to decipher.

    Friday, March 22, 2013 6:58 PM
  • Thank you for sticking to guns on corruption.  A heap corruption was the root cause for this weird behavior.  Your answer helped me retrospect the code find the corruption point.

    Saturday, March 23, 2013 11:13 AM
  • Thank you for sticking to guns on corruption.  A heap corruption was the root cause for this weird behavior.  Your answer helped me retrospect the code find the corruption point.

    Told you that . That's why it is akways to check for empty condition on a map before performing any further operation on it.

    Thanks


    Rupesh Shukla

    Monday, March 25, 2013 1:32 PM