1

There is a function that changes the value "bIsTrue" to true after 2sec. When bIsTrue is "true", the main thread can escape while loop and print out "Now bIsTrue is True!" in main()

#include <iostream>

#include <process.h>
#include <Windows.h>

using namespace std;

bool bIsTrue; // global variable
unsigned __stdcall Func(void* pArg)
{
    Sleep(2000);
    bIsTrue = true;
    
    return 0;
}

and this is main(). but when there is nothing in while loop, the main thread do not print "Now bIsTrue is True!" in release mode.

int main()
{
    // bIsTrue will be "true" after 2sec.
    bIsTrue = false;
    HANDLE tHandle = (HANDLE)_beginthreadex(NULL, 0, Func, NULL, 0, NULL);
    CloseHandle(tHandle);

    size_t i = 0;
    while (!bIsTrue)
    {
        // If here is a nothing, main thread can't escape this loop in Release mode.
        // but can escape in Debug mode.

        // When here is Sleep() or cout, main thread can escape this loop in both mode.
        // Sleep(1000);
        // OR
        // cout << i++ << endl;
    }

    cout << "Now bIsTrue is True!" << endl;

    return 0;
}

this is the result when print 'i' in the loop.

enter image description here

Can you guys understand why I got this result?

woohyeon
  • 29
  • 6
  • Isn't an infinite loop Undefined Behavior? – drescherjm Nov 12 '20 at 04:29
  • Why are you closeHandle-ing? Does that stop the thread? I would suggest using C++ cross-platform thread utilities. – Anonymous1847 Nov 12 '20 at 05:09
  • drescherjm // But adding Sleep or court is also still infinite loop. isn't it? – woohyeon Nov 12 '20 at 05:11
  • Sometimes with UB a little change has a drastic change in behavior. – drescherjm Nov 12 '20 at 13:15
  • Related: [https://stackoverflow.com/questions/41320725/is-infinite-loop-still-undefined-behavior-in-c-if-it-calls-shared-library](https://stackoverflow.com/questions/41320725/is-infinite-loop-still-undefined-behavior-in-c-if-it-calls-shared-library) – drescherjm Nov 12 '20 at 13:20

1 Answers1

2

What may be happening is that your flag variable is being optimized out by the compiler because it think it can't change. Here is a case you could use volatile, and also std::atomic:

volatile std::atomic<bool> bIsTrue = false;

Also, I would check your use of WinAPI functions. I would suggest instead using the standard C++ thread library: https://en.cppreference.com/w/cpp/header/thread .

Anonymous1847
  • 2,568
  • 10
  • 16
  • Thank you! a compiler optimization was the problem.. and _beginthreadex is for my Windows game programming. thank you. – woohyeon Nov 12 '20 at 05:18
  • 1
    Note that `volatile` is *not* actually what helps you in this case. It's `std::atomic` that alerts the compiler that the variable's reads and writes must be serializable between threads, and thus prevents it from optimizing out the read in the while loop. See https://stackoverflow.com/questions/26307071/does-the-c-volatile-keyword-introduce-a-memory-fence – Edward Nov 12 '20 at 05:36
  • Edward // I appreciate it! – woohyeon Nov 12 '20 at 05:46