0

Ran into a problem in VS2013, and was asking HOW COULD THIS HAVE EVER WORKED?
A customer had the following macro in production. (specifics have been changed)

#define IS_NONE( charPtr )  ( ( charPtr == "none" || charPtr == "N/A" ) ? TRUE : FALSE )

My problem was the code was crashing when a block named "none" was requested. The code should have identified a "none" block and skipped requesting the block. But it failed to do so?
I knew the customer code was running production in VS6.0, but was only crashing in VS2013. The Answer is below.

Ross Youngblood
  • 502
  • 1
  • 3
  • 16

1 Answers1

0

The test case below builds in Visual Studio 6.0.

The default Visual Studio6.0 behavior is "Program Database with Edit and Continue". Turns out this enables STRING POOLING. So the compiler sweeps through and optimizes ALL compile time strings into a pool, and duplicate strings are ELIMINATED. So all literal definitions of "none" and "N/A" below will POINT TO THE SAME PHYSICAL ADDRESS. As a result the string compare appears to work.

Any dynamically created strings will fail to match, as their addresses will always be unique.

To get this test case to FAIL build it with "Program Database" in VS 6.0 (See screenshot below).

//
// Slight changes to my program from what I compiled
#include "stdio.h"
#define IS_NONE( a_key )   ( ( a_key == "none" || a_key == "N/A" ) ? TRUE : FALSE )

HOST_BEGIN_BLOCK( TestCase ) {
    char *psNameNone = "none";
    char *psNameNA   = "N/A";
    char *psNameCAT  = "CAT";

    if (IS_NONE(psNameNone) ) {
        printf("psNameNone Matches NONE\n");
        printf("%s psNameNoneAddr 0x%x  \"none\" addr 0x%X\n",
            psNameNone,psNameNone,
            "none");
    } else {
        printf("psNameNone Does Not Match None\n");
        printf("%s psNameNoneAddr 0x%x  \"none\" addr 0x%X\n",
            psNameNone,psNameNone,
            "none");
    }

    if (IS_NONE(psNameNA) ) {
        printf("psNameNA Matches N/A\n");
        printf("%s psNameNA 0x%x  \"N/A\" addr 0x%X\n",
        psNameNA,psNameNA,
        "N/A");
    } else {
        printf("psNameNone Does Not Match N/A\n");
        printf("%s psNameNA 0x%x  \"N/A\" addr 0x%X\n",
        psNameNA,psNameNA,
        "N/A");
    }
    if (IS_NONE(psNameCAT)) {
        printf("psNameNA Matches CAT\n");
        printf("%s psNameNA 0x%x  \"CAT\" addr 0x%X\n",
        psNameNone,psNameNone,
        "CAT");
    } else {
        printf("psNameNA does not match CAT\n");
        printf("%s psNameNA 0x%x  \"CAT\" addr 0x%X\n",
        psNameNone,psNameNone,
        "CAT");
    }
}

ProgramDatabaseShot

Below is an image of the test case passing. Note that all the string ADDRESSES are the same.

Built with "Program Database With Edit and Continue" Passing Test Case--Should fail

This is the test case failing, as one would expect for an incorrect Compare syntax.

Built with "Program Database" Failing Test Case--Expected Behavior

Hopefully this will help others trying to figure out why VS6.0->Modern compiler ports appear to work on VS6.0 (1998 compiler) but fail with a modern compiler.

Ross Youngblood
  • 502
  • 1
  • 3
  • 16