Click here to Skip to main content
15,911,711 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm moving my app (now v10.4) C++ code base to VS2012 from VS2008. In VS2008 it's been working perfectly for years. Under VS2012 Debug, it runs perfectly as well, but in Release mode, a very simple test (decoding an LPSTR buffer created with the new operator) gets the address off by 1 and the decode fails. I'm very familiar with guard bytes in debug mode.

For example, I can create the simplest 4 byte buffer containing "\rI:0x1a". There's a pointer (lpScript) to the start of the buffer. All the decode function has to do is
(in pseudo code)
lpScript++;
TestNextCharIsAlpha();
lpScript++;
TestNextCharis Colon();

Simple, right? Well, not so.


The VS2012 compiler Release mode seems to handle byte alignment differently to debug mode and the 2008 compiler. In Debug mode, TestNextCharIsAlpha(); is testing the "I" character. In Release mode, TestNextCharIsAlpha(); is testing the ":" character. The values of the lpScript look correct, and still there's this bug. And as I said, this code has been working for years when built with VS2008.

I've poked around in the project setups and can't find anything that explains this. Any ideas?
Posted
Comments
[no name] 21-Jul-13 23:23pm    
The actual code you are using would be helpfull. Is this a Unicode compile?

I would think that instead of the alignment being different between debug/release, instead it is the size of the structure that is different. Look at the definition for the class/struct and see if there is any "#ifdef _DEBUG" or similar code in it (actually you need to do this recursively if your class contains other classes).

This kind of problem can also occur if you do your own memory management. If you don't know what that means, look to see if any of your classes implement operator new (both types) and/or use a memory pool. The memory allocation needs to be aligned properly; many times it is not done properly. This is a common memory management mistake.
 
Share this answer
 
Comments
nv3 22-Jul-13 3:13am    
You might have hit the nail, Harvey. Without any code it's hard to tell. +5
This has nothing to do with "byte alignment". Bytes in a byte array are always allocated contiguous to each other, at least on the Intel architecture. Alignment would set in if you have e.g. a double member in a structure and the compiler has to decide whether to align it on a 8-byte boundary or not.

In your case the bug sits most likely in your own code, which you unfortunately haven't shown. Look at how lpScript is initialized. Why is lpScript not passed to TestNextCharIsAlpha? I'd take a close look on what you are doing there. If you like, paste your code with "Improve question" so we can a look at it.
 
Share this answer
 
Thanks for the suggestions. I have found a code solution, but have no clue at present why it matters to the VS2012 compiler. A bit of history: the app is a language interpreter I first wrote in 1992 with VC4. The code base progressed through VC5,VC6,VS2003 and VS2008, and the relevant section of code never required updating until I switched to VS2012.

The interpreter uses
extern LPSTR lpScriptIP; // loaded from the app script code file.

// Here's the section of code that was breaking in VS2012 Release mode. The 
// content of lpScripIP was   "\rI:0x1a"

BOOL CheckPointLabel (VOID)
{
    extern LPSTR lpScriptIP;
	
    /* Check whether point is the start of an identifier or label.
     lpScriptIP does not get modified. */

    if (FALSE == CheckPointIdentifier ())
    {
	 return (FALSE);  
    }

    /* Check whether character before starting point is an EOL: CR, LF or EOF */

    --lpScriptIP;   
	 
    // Call the updated CheckCharEOL that passes the script pointer
    // instead of using the extern pointer.
    // I found that a MessageBox call to report details here was all that
    // required the bug to go away. Similarly, a SetTimer(NULL, NULL,1,NULL); 
    // call would also remove the bug. Neither were an acceptable solution. 
    // Eventually, I updated the call to pass lpScriptIP to the function.
 
    if (FALSE == CheckCharEOL_new (lpScriptIP))
    {
        return (FALSE);  // Point is not the start of a label
    }
    
    ++lpScriptIP;   // Reset script pointer to start of label

    /* Check whether identifier is followed by CHAR_LABEL_END (:) */

    ScanIdentifierEnd();

    if (*lpScriptIP != CHAR_LABEL_END)
	 return (FALSE);
	
    ++lpScriptIP;

    /* Point is the start of a label */

    return (TRUE);
}


// Here's the old and new versions of the CheckCharEOL function.
 
BOOL CheckCharEOL_old (VOID)
{
    extern LPSTR lpScriptIP;

    switch (*lpScriptIP) 
    {
       case CHAR_CR:
       case CHAR_LF:
       case CHAR_EOF:
	 return (TRUE);

       default:
	 return (FALSE);
    }
}

BOOL CheckCharEOL_new (LPSTR lpScript)
{
    switch (*lpScript) 
    {
       case CHAR_CR:
       case CHAR_LF:
       case CHAR_EOF:
	 return (TRUE);

       default:
	 return (FALSE);
    }
}


I'm at a loss to explain why VS2012 Release mode has a problem with this. The solution I now have has passed all the language interpreter tests, so I'm happy to leave it alone for now.

It's almost as though the lpScriptIP was not being decremented before it was passed to the CheckCharEOL_old() function.

All theories to explain this are appreciated. The app language is called PiXCL.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900