Thread: Odd release build behavior in MSVC 2005

  1. #1
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607

    Odd release build behavior in MSVC 2005

    The following lines of code do not produce the correct values in release builds in MSVC 2005. Note that m_rect is a RECT and its members have been set to zero prior to this. Vector3 is a struct with 3 floats x,y and z. These lines do work in debug builds.
    Code:
        Vector3 pos = m_pFrame->GetPosition();
        Vector3 scale = m_pFrame->GetScale();
        
        m_rect.left = static_cast<LONG>(pos.x - (scale.x * 0.5f));
        m_rect.right = m_rect.left + static_cast<LONG>(scale.x);
        m_rect.top = static_cast<LONG>(pos.y - (scale.y * 0.5f));
        m_rect.bottom = m_rect.top + static_cast<LONG>(scale.y);
    These lines work in release builds and debug builds.
    Code:
        
        Vector3 pos = m_pFrame->GetPosition();
        Vector3 scale = m_pFrame->GetScale();
        
        float scaleX2 = scale.x * 0.5f;
        float scaleY2 = scale.y * 0.5f;
        float left = pos.x - scaleX2;
        float top = pos.y - scaleY2;
        float right = left + scale.x;
        float bottom = top + scale.y;
        m_rect.left = static_cast<LONG>(left);
        m_rect.right = static_cast<LONG>(right);
        m_rect.top = static_cast<LONG>(top);
        m_rect.bottom = static_cast<LONG>(bottom);
    Why does the first example only work in debug builds and not release builds? Are they not syntactically the same lines of code? Is my FPU possibly in a bad state prior to executing these lines and somehow debug is resetting the state so they work or is it something else?

    Here is an example output in release using the first block of code:
    Cell rectangle: PosX: 75.000000 - PosY: 487.500000 - ScaleX: 100.000000 - ScaleY: 15.000000, Top: -1012 - Left: 74 - Right: 124 - Bottom: -997
    Here is an example output in release using the second block of code:
    Cell rectangle: PosX: 75.000000 - PosY: 487.500000 - ScaleX: 100.000000 - ScaleY: 15.000000, Top: 480 - Left: 25 - Right: 125 - Bottom: 495
    Any ideas?

  2. #2
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    Where's the printing code? If it's the very next line after these pieces, then the compiler is dodgy. If it's later on, set a data breakpoint and see who or what is overwriting the values.

  3. #3
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    The printing code is immediately after the calculations. I removed all code between the calculations and the printing just to be sure no other methods were messing the values up or somehow hosing the memory. I think the compiler is at fault here. I have sent this code to some co-workers and talked with them as well and they also cannot see why the first block of code would not work in release.

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    There is insufficient evidence to say the compiler is at fault.

    Firstly, the second code is not quite equivalent to the first in the calculations of m_rect.right and m_rect.bottom (conversions of float <-> LONG occur in different sequence).

    Second, if adding variables changes results of your program, or changing from debug to release mode, causes code to behave differently, the most common cause is some other code executed previously that is exhibiting undefined behaviour. If some other code is trashing m_pFrame, it may cause members of pos and scale to have different values ..... which would mess up your calculations and output.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  5. #5
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    Have you already yanked that code from its home and tried it?

    Soma

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    No I have not tried the code by itself. My guess is it would probably work. Perhaps the FPU is in a bad state prior to executing the code in my function.

    If some other code is trashing m_pFrame, it may cause members of pos and scale to have different values ..... which would mess up your calculations and output.
    Although m_pFrame is a pointer the only object with access to it is the object using it. It is created by the object, used by the object, and not exposed outside of the object. I checked the code in m_pFrame for position and scale and they are D3DXVECTOR3 structures and are on the stack inside of the frame class.

    m_pFrame is valid and all its members are correct as well as the values of pos.x, pos.y, pos.z and scale.x, scale.y, and scale.z as verified by printing the values out. After changing the code to match the second block the program runs fine and everything 'appears' to work. Perhaps there is something else wrong prior to this and this little section of code is leading me off into the weeds. I am definitely not opposed to the idea that something else in the code is amiss which is causing this behavior. This was my first suspicion and usually is when I get weird or unexpected behavior such as this.

    Firstly, the second code is not quite equivalent to the first in the calculations of m_rect.right and m_rect.bottom (conversions of float <-> LONG occur in different sequence).
    Yes this is correct. However would that not mean that at least m_rect.left and m_rect.top would be correct and m_rect.right and m_rect.bottom would be incorrect? Since they are all incorrect I doubt this is the issue.

    I will look into the code some more to see if I can find anything that occurs before this that could possibly cause undefined behavior to occur. Somehow I don't think this is going to be simple to find.

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by VirtualAce View Post
    Although m_pFrame is a pointer the only object with access to it is the object using it. It is created by the object, used by the object, and not exposed outside of the object. I checked the code in m_pFrame for position and scale and they are D3DXVECTOR3 structures and are on the stack inside of the frame class.

    m_pFrame is valid and all its members are correct as well as the values of pos.x, pos.y, pos.z and scale.x, scale.y, and scale.z as verified by printing the values out. After changing the code to match the second block the program runs fine and everything 'appears' to work. Perhaps there is something else wrong prior to this and this little section of code is leading me off into the weeds. I am definitely not opposed to the idea that something else in the code is amiss which is causing this behavior. This was my first suspicion and usually is when I get weird or unexpected behavior such as this.
    Unfortunately, none of the things you have verified here mean much if some other code is writing to memory it shouldn't. That is why I suspect, somewhere in code you haven't shown, there is code exhibiting undefined behaviour of some form.

    Quote Originally Posted by VirtualAce View Post
    Yes this is correct. However would that not mean that at least m_rect.left and m_rect.top would be correct and m_rect.right and m_rect.bottom would be incorrect? Since they are all incorrect I doubt this is the issue.
    I agree this is not likely to be the cause of your symptoms. However, it is another issue with your code. I considered I should point it out, as your original post seemed to suggest your two code fragments are equivalent, when they do actually have slightly different effects.

    Quote Originally Posted by VirtualAce View Post
    I will look into the code some more to see if I can find anything that occurs before this that could possibly cause undefined behavior to occur. Somehow I don't think this is going to be simple to find.
    Arguably the most common causes are pointer molestations (dereferencing a NULL or uninitialised pointer, dereferencing a dangling pointer or reference, releasing an object more than once, or falling off the end of an array [which is also applicable to standard containers depending on how you access elements]). I'm not eliminating other possibilities, but those are the types of problems I'd look for first.

    But, yeah, these types of errors usually are hard to find ..... particularly as the symptoms are sensitive both to small changes of code, and to compilation options.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  8. #8
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Have you tried starting with the second code snippet which works, and transforming it towards looking like the first code snippet one step at a time, compiling and running the code after each change?
    Whatever change it is that introduces the first incorrect result will be interesting to know. It may suggest that certain things are a lot more likely than others.
    It might be tedious, but it should definitely help getting an answer as to what is going on.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  9. #9
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    There are known bugs in 2005 floating point optimizer. If you add "/fp:strict" to switches, does it work?
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  10. #10
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Quote Originally Posted by brewbuck View Post
    There are known bugs in 2005 floating point optimizer. If you add "/fp:strict" to switches, does it work?
    Hmmm. Good information. I will try that and let you know the results.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Directx Release Build
    By ybobjoe in forum C++ Programming
    Replies: 2
    Last Post: 02-25-2010, 08:49 PM
  2. Error 87 in release build
    By CrissyCrisCris in forum Windows Programming
    Replies: 3
    Last Post: 09-19-2009, 06:52 PM
  3. build/release engineering
    By bling in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 11-24-2008, 06:29 PM
  4. MSVC 2005 Express Distribution Build?
    By Kurisu33 in forum Windows Programming
    Replies: 12
    Last Post: 11-01-2006, 11:09 AM
  5. Replies: 2
    Last Post: 05-22-2004, 02:10 AM