none
Visual Studio 2017 crashes if I set a breakpoint in startup code RRS feed

  • Question

  • Hi - until recently, I used Visual Studio 2010 to build my large C++, MFC (unmanaged, and not .net) application.   About a month ago I upgraded to Visual Studio 2017 and was able to get my application to build with less trouble than I expected.  I continued developing my application using Visual Studio 2017.  Two days ago I hit a strange problem when my application started crashing at startup.  It took me a while to realise it, but the problem turned out not to be caused by any change I'd made to the code.  It was caused by the fact that I had just set a breakpoint in a particular section of the startup code.  If I remove this breakpoint, the program runs fine and no exceptions are thrown.  If the breakpoint is in the wrong place though, it throws an exception every time.

    I have since gone back to the first build of my application using Visual Studio 2017 and have discovered that it too will crash if I set a breakpoint in various different places (but not all) within the startup code.  Typically what happens is that I get an exception like this at the site of the breakpoint:

    "Unhandled exception at 0x0F2C9BE6 (mfc140ud.dll) in <my executable>.exe: 0xC0000005: Access violation reading location 0x00000028."

    Depending on where I place the breakpoint, sometimes the exception may not be (apparently) anywhere near it.  For example, sometimes it is shown as occurring in the destructor of an object that doesn't, as far as I can see, have an instance anywhere near the breakpoint.  In this case, the call stack looks like garbage and the exception message is:

    "Exception thrown: write access violation.
    this was nullptr."

    The line I'm trying to break on in this case is an assignment of 'true' to a boolean (a static data member).  If I move the breakpoint to the previous line (which assigns the result of a function call to the same boolean), I get an exception actually at the breakpoint  which says "Exception thrown at 0x00FF45F1 in <my executable>.exe: 0xC0000005: Access violation reading location 0xCD19F404."

    The second line assignment is within a #ifdef _DEBUG/#endif pair.  I tried commenting these out to see if it made any difference but it didn't (thankfully! It's a mad enough situation already without that).

    Incidentally, if I set a breakpoint within the destructor of the object in question, it breaks there fine with no exceptions being thrown (unless I also set a breakpoint in one of the forbidden areas).

    I can live without being able to set these breakpoints, but I'm concerned that it is a symptom of a more serious underlying problem.  Can anyone suggest what I can do to investigate these bizarre symptoms?  Is there, for example, any way of getting Visual Studio to log more information about what is happening, which might mean something to someone?

    All help very much appreciated.


    Simon

    Tuesday, April 10, 2018 4:34 PM

All replies

  • 0xC0000005 stand for that you are trying to read from an invalid location. Did you tried to debug your code to see at what point you are getting this error.Looks like it is not happening all the time in your code it can be some time issue . Try to break the assertion at the time of debug and see what's going on.

    Thanks


    Rupesh Shukla

    Tuesday, April 10, 2018 5:16 PM
  • Thanks for the reply but you don't seem to have read what I said.  It happens every time I set a breakpoint in certain sections of the startup code.  And it never happens if I don't set a breakpoint or don't set one in these sections of startup code.

    You ask "Did you tried to debug your code".  Everything that I'm doing is happening in DEBUG mode.  I'm setting breakpoints and this causes my app to crash.  My question is - how do I debug that?


    Simon

    Tuesday, April 10, 2018 8:34 PM
  • I am not sure what Rupesh was trying to say but the word "debug" in tat context is ambiguous. One possible interpretation is that Rupesh is suggesting you (using the debugger) get more information about what is happening. I agree however that Rupesh's comments are not totally clear to me.


    Sam Hobbs
    SimpleSamples.Info

    Wednesday, April 11, 2018 1:01 AM
  • One thing you can do is to look at the debug output when you execute with the debugger without the breakpoint. There might be a line about a first-chance exception. You could easily know more about that than I do but I know that MFC often does some second-level exception handling. I am totally guessing but it might be that there is a first-level exception that normally gets fixed later.

    I probably cannot help except to say that anyone that can help is likely to want details of the code. It is especially relevant to know if the code is doing something that should be fixed. You have provided no source code but if you think about it from the point of view of someone trying to help, there are too many possibilities, we need more specific information about what is happening.



    Sam Hobbs
    SimpleSamples.Info

    Wednesday, April 11, 2018 1:23 AM
  • Did you have a look at Disassembly, when exception occurs? Does it look 'sane'?
    Very rare - and in these cases probably would have expected more a 'illegal instruction' exception - the breakpoint-instruction (0xcc) then was erroneously not placed at the beginning of a multi-byte opcode, but in the middle.

    With kind regards    

    Wednesday, April 11, 2018 8:51 AM
  • Hi - thanks for the ideas.  If I run the code with no breakpoint it starts up fine and no exceptions are thrown (or there is no mention of any in the debug output).  I don't think providing source code will help.  The original line of code that I set the break point on is this:

    a = true;

    where 'a' is a static member variable (not the original name obviously).  If I set a breakpoint there it still crashes every time with - but the call stack shows garbage and the exception ("write access violation.  this was nullptr'") is in an object (derived from CFile) that is nowhere near the breakpoint.

    So what source code should I provide?  The exceptions don't seem to correlate with any, in any way.  This is a very large application with a mountain of source code, and I have no idea which part - if any - is even relevant.

    I'm really looking for some ideas about how to try to investigate the problem.


    Simon

    Wednesday, April 11, 2018 8:52 AM
  • a = true;

    where 'a' is a static member variable (not the original name obviously).  If I set a breakpoint there it still crashes every time with - but the call stack shows garbage and the exception ("write access violation.  this was nullptr'") is in an object (derived from CFile) that is nowhere near the breakpoint.

    So what source code should I provide? 

    Hello,

    Show us the class declaration of variable a in the feader file. Should be:

    class XYZ
    {
      //...
      static bool a;
      //...
    };

    And the definition of the variable a in the source file. Should be:

    bool XYZ::a = false; // or true

    Is it this way?

    If it is, show us the line directly before a=true.

    Regards, Guido

    Wednesday, April 11, 2018 8:59 AM
  • Relevant link:
    https://software.intel.com/en-us/forums/intel-c-compiler/topic/489007?page=1
    Problem is certainly that it happens at startup, so attaching windbg noninvasively and checking relevant opcodes during the run of application in VS - (Visual Studio must not be in break-mode!) - is not possible.
    But probably you can start and later on add relevant bps at these places (when it is safe to do so) for verifying.  

    With kind regards

    Wednesday, April 11, 2018 9:23 AM
  • Following my last post, it occurred to me that I could try and find out where the exception was really being thrown by saturating my startup code with trace-logging calls that output the code position to an external trace-log text file (this is my own trace-log code incidentally that I have used before).  I already had some of these startup trace-logs.  They are #defined so that I can enable them or disable them easily.  So I just needed to enable them.  When I did so, the log file data implied that the exception was being thrown somewhere in the function that the breakpoint was being set in.  However, just by enabling trace logs, I had somehow changed things and the exception was now being described as appearing in a completely different object and code position to previously (i.e. not the actual breakpoint and not the destructor of the CFile-derived object).  To be honest, the exception information looks like complete garbage to me - just as the call stack does.   However, that seemed like progress of sorts.  So I added 2 more trace calls - before and after the breakpoint line.  So where previously I set my breakpoint on 

    a = true;

    I now set the breakpoint on the same line, but this time put trace log calls before and after it, like this:

    TRACE_LOG(L"Reached code position 36");
    a = true;
    TRACE_LOG(L"Reached code position 37");

    That was the only change I made: the addition of the 2 extra TRACE_LOG lines.  But now the exception isn't thrown any more!  The code breaks on "a = true;" with no exceptions thrown, and executes fine if I click 'Continue'.  And it does so completely consistently - every time.  It also runs fine if I don't place a breakpoint at all.  But if I comment out the first of the two TRACE_LOG lines, and set a breakpoint on "a = true;" I get an exception again (in an apparently random area of my code).

    I then tried moving the TRACE_LOG one line back.  The line before "a=true;" is like this "a=Func();".  So we now have this

    TRACE_LOG(L"Reached code position 36");
    a=func();
    a = true;
    TRACE_LOG(L"Reached code position 37");

    If I set the breakpoint on "a=func();" it breaks fine - no problem.  If I set the breakpoint on "a = true;" I get a garbage exception - but the log file's last line is "Reached code position 36" which shows that the exception is thrown on either "a=func();" or "a=true;" which confirms that the exception information is, as I thought, total garbage.

    Can someone from Microsoft step in at this point?  I can't see any way that you can interpret the above, except as a bug in Visual Studio 2017 (C++). 


    Simon

    Wednesday, April 11, 2018 10:05 AM
  • In case anyone is wondering, the function in the "a=func();" call is a very trivial function which is used all over the place without problems and looks like this:

    bool UtRegReadBool(HKEY hKey, const wchar_t *pKey, bool bDefault, wchar_t *pBuffer, DWORD dwLen, bool *pbSet /* = NULL */)
    {
    	DWORD dwType;
    	DWORD dwTemp = (dwLen * sizeof(wchar_t));
    	long lResult = ::RegQueryValueEx(hKey, pKey, NULL, &dwType, (LPBYTE)pBuffer, &dwTemp);
    	if (lResult == ERROR_SUCCESS && dwType == REG_SZ)
    		{
    		if (pbSet)
    			*pbSet = true;
    		return (_wcsicmp(pBuffer, L"TRUE") == 0);
    		}
    
    	if (pbSet)
    		*pbSet = false;
    	return bDefault;
    }
    

    Instead of "a = func();" (which was simplification for clarity) the call actually looks like this:

    a = UtRegReadBool(hKey, PREFS_WD_FS_FW_ICON, s_WdFsPaintFocusWindowIcon, cBuffer, MAX_REG_DATA_LEN);

    In the call, pbSet is not given as a parameter (it defaults to NULL if not provided) but other values are normal (the breakpoint line follows numerous calls to the same function with all parameters the same, except the pKey value and bDefault value).  In other words, I don't think the function can possibly be the problem.


    Simon

    Wednesday, April 11, 2018 10:12 AM
  • So what source code should I provide?  The exceptions don't seem to correlate with any, in any way.

    The symptoms seem to be consistent with incorrect memory access. It could be that something is changing memory it should not. If that is happening then that could explain why adding instructions that are otherwise unrelated to the cause causes different behavior.

    You are getting violations accessing memory at varying locations, such as at 0x00000028 and 0xCD19F404. So it could easily be caused by something altering the location of something. Whatever it is, the item is actually at a different location than what is being used and the reason for that is that something is changing the pointer, or something like that.

    So first you need to determine what the item is that has had its location changed incorrectly. The important thing you need is the location of the pointer that is being incorrectly changed. Then you can put a breakpoint on the very first code that is executed (hopefully that is prior to the problem) then execute with the debugger (of course) and when the initial breadkpoint is hit create a data breakpoint for the pointer. Are you familiar with data breakponts? You will then get a break when the data changes.



    Sam Hobbs
    SimpleSamples.Info

    Wednesday, April 11, 2018 6:52 PM