This answers "what is different", but may not be the full answer to why your code has a race condition in release mode.
One thing that changes is which heap is being used by the runtime, when you move to release outside of VS. It uses a debug heap inside VS even in release mode, as far as I understand.
Since heap allocations by definition has to be locked, using the debug heap (which fills the memory before it's given to the client code, and fills it again when the memory is freed) will block competing threads more often (causing more sequential execution), so you may find that this is part of the reason that the race happens.
If you set the environment variable _NO_DEBUG_HEAP=1
in your debug environment, (Configuration->Debugging->Environment Variables...), then you will get the same thing in the debugger.
Unfortunately, these sort of things can be quite tricky to debug. One thing I've found useful is to store an array of values for "where I've been" (the simpler the array, the better - so integer values, or a small string, or something), rather than printing something every time. If you can stop in the debugger or detect the crash in some way, you can then dump the "trace", and see how you got to where you are now, and what threads were involved.