When is a divide by zero not a divide by zero? A puzzle in the debugger (static variable issues)

后端 未结 2 2003
面向向阳花
面向向阳花 2020-12-11 01:02

I\'m very confused and I think my debugger is lying to me. I have the following loop in my code:

MyClass::UploadFile(CString strFile)
{
  ...
  static DWORD         


        
相关标签:
2条回答
  • 2020-12-11 01:58

    The problem may be related to multithreading.

    1. A thread enters the function
    2. Checks the hidden "is_initialized" static variable to see if initialization has already been performed
    3. The var is 0, so it sets the variable to 1 and proceeds reading the registry
    4. At this point another thread enters the function
    5. The second thread sees the variables as already initialized and skips the initialization code
    6. The division is performed when the denominator is still 0 (the first thread is still reading the registry)
    7. The program crashes, but in the meanwhile the first thread completes execution, setting the variables that you see in the dump.
    8. You lose sleep thinking how the impossible happened
    0 讨论(0)
  • 2020-12-11 02:03

    Since the code is part of a member function, and you're calling this function from multiple threads, the static variables are not thread-safe if using a compiler that does not conform to C++ 11 standards. Thus you may get data races when initializing those two static variables.

    For a C++ 11 standard conforming compiler, static variables are now guaranteed to be initialized by the first thread, while subsequent threads wait until the static is initialized.

    For Visual Studio 2010 and below, static local variables are not guaranteed to be thread safe, since these compilers conform to the C++ 03 and C++ 98 standard.

    For Visual Studio 2013, I am not sure of the level of C++ 11 support in terms of static local initialization. Therefore, for Visual Studio 2013, you may have to use proper synchronization to ensure that static local variables are initialized correctly.

    For Visual Studio 2015, this item has been addressed and proper static local initialization is fully implemented, so the code you currently have should work correctly for VS 2015 and above.


    Edit: For Visual Studio 2013, static local thread-safe initialization is not implemented ("Magic Statics"), as described here.

    Therefore, we can cautiously verify that the reason for the original problem is the static-local initialization issue and threading. So the solution (if you want to stick with VS 2013) is to use proper synchronization, or redesign your application so that static variables are no longer needed.

    0 讨论(0)
提交回复
热议问题