0

I am using VS2015.

In debug mode highlighted while loop works correct - when !P_Object->first_request is true it breaks.
But same conditions doesn't work in release mode. Moreover in quickwatch you can see that visual studio quickwatch recognize !P_Object->first_request as false, but loop continue repeating.

BTW: P_Object->first_request variable initialized as false in class and changing on true in thread (maybe this information is helpful - idk).

enter image description here

How to fix this bug?

DEBUG Command line - "/GS /analyze- /W3 /Zc:wchar_t /I"C:\boost_1_62_0" /ZI /Gm /Od /Fd"Debug\vc140.pdb" /Zc:inline /fp:precise /D "WIN32" /D "WIN32_LEAN_AND_MEAN_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /Oy- /MTd /Fa"Debug\" /EHsc /nologo /Fo"Debug\" /Fp"Debug\ExpenditureAndReceipts.pch"";

RELEASE Command line - "/GS /analyze- /W3 /Gy /Zc:wchar_t /I"C:\boost_1_62_0" /Zi /Gm- /O2 /Fd"Release\vc140.pdb" /Zc:inline /fp:precise /D "WIN32" /D "WIN32_LEAN_AND_MEANNDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Gd /Oy- /Oi /MT /Fa"Release\" /EHsc /nologo /Fo"Release\" /Fp"Release\ExpenditureAndReceipts.pch"";
Macmade
  • 49,018
  • 12
  • 104
  • 121
Eugene
  • 109
  • 8
  • 3
    i guess that its been optimized out, since the loop does nothing – pm100 Jan 06 '17 at 00:35
  • 1
    You might want to mark the variable `volatile` to tell the compiler to not optimize out its uses. – Some programmer dude Jan 06 '17 at 00:36
  • 1
    You need to use proper inter-thread synchronization (*not* just slapping `volatile` on the variable). Use an atomic data type, critical section, mutex, or whatever is appropriate. – Michael Burr Jan 06 '17 at 00:45
  • 1
    To put together the points made in my previous comment, and the one by @MichaelBurr, into a single comment: The optimization problem can be solved with `volatile`, but it is not a thread-synchronization keyword. You still need proper synchronization for the access. And as a sidenote, don't use busy-waiting loops. A better solution altogether might be something like condition variables (and will solve both problems). – Some programmer dude Jan 06 '17 at 00:53
  • Like @pm100 mentioned in comment above the problem was that compiler optimezed out loop because it was empty. Thx! – Eugene Jan 06 '17 at 10:12

2 Answers2

3

You cannot read a bool in one thread and write it in another. The compiler is free to cache the read in the first thread, and never read the memory change.

If you are writing multi-threaded programming, communicate through atomics and mutexes and the like.

Replace first_request with an std::atomic<bool>. This may require changing other code. When done, things should be good.

What you did (read in one thread, write in another, no synchronization) is undefined behavior. Undefined behavior doesn't always crash, it sometimes just results in release builds not making sense.

Yakk - Adam Nevraumont
  • 235,777
  • 25
  • 285
  • 465
  • Can you cite/recommend a source for more information on your first statement? Apparently I have been writing wrong multithreaded code for years now and would like to read up on that... – Jack White Feb 01 '17 at 14:05
  • 1
    @JackWhite [This awesome SO post](http://stackoverflow.com/a/6319356/1774667) describes the C++11 threading model. Basically, C++03 doesn't define how threading works. C++11 defines a model, and in it a read and a write without some kind of synchronization (there are many ways it can be synchronized, not just a mutex) is simply undefined behavior. Full stop. The case where the value is cached in one thread and never re-read from memory, well, I've seen it happen, and seen it covered in SO questions, but not sure what to cite. – Yakk - Adam Nevraumont Feb 01 '17 at 14:40
-1

Essentially a release only bug has to be tackled exactly like any other bug, except you have no machinery to help you. Reduce the application to "Hello World" - something that gives a bit of output and shuts down without error. Then put the whole application back in, and add a toggle so you can toggle between the bug-free "Hello world" version" and the bugged version with a few keystrokes.

Now add functionality to the Hello World version and take it out of the complete version (keeping a complete version, of course). Try to isolate the point where the bug appears, so you can toggle between a bug-free, slightly crippled and a bugged version with a few keystrokes.

That often reveals the bug. If it doesn't, start using that information to put in diagnostic printf (get a debug console up and running so you can see stdout).

Release zero-initialises memory allocated with malloc(), asserts are different, and there are many other small changes. It's not too uncommon to have a release-only bug, although of course it makes debug mode pointless.

Malcolm McLean
  • 6,063
  • 1
  • 13
  • 18
  • There are no release-only bugs, only bugs that show up differently (and more severely) in release mode. – Ben Voigt Jan 07 '17 at 05:27