What are the dangers of uninitialised variables?

前端 未结 4 1483
-上瘾入骨i
-上瘾入骨i 2021-01-18 20:38

In a program I am writing I currently have several uninitialised variables in my .h files, all of which are initialised at run-time. However, in Visual Studio it warns me ev

相关标签:
4条回答
  • 2021-01-18 21:04

    These variables could contain any value if you don't initialize them and reading them in an uninitialized stated is undefined behavior. (except if they are zero initalized)

    And if you forgot to initialize one of them, and reading from it by accident results in the value you expect it should have on your current system configuration (due to undefined behavior), then your program might behave unpredictable/unexpected after a system update, on a different system or when you do changes in your code.

    And these kinds of errors are hard to debug. So even if you set them at runtime it is suggested to initialize them to known values so that you have a controlled environment with predictable behavior.

    There are a few exceptions, e.g. if you set the variable right after you declared it and you can't set it directly, like if you set its value using a streaming operator.

    0 讨论(0)
  • 2021-01-18 21:10

    There are two parts to this question: first is reading uninitialized variables dangerous and second is defining variables uninitialized dangerous even if I make sure I never access uninitialized variables.

    What are the dangers of accessing uninitialized variables?

    With very few exceptions, accessing an uninitialized variable makes the whole program have Undefined Behavior. There is a common misconception (which unfortunately is taught) that uninitialized variables have "garbage values" and so reading an uninitialized variable will result in reading some value. This is completely false. Undefined Behavior means the program can have any behavior: it can crash, it can behave as the variable has some value, it can pretend the variable doesn't even exist or all sorts of weird behaviors.

    For instance:

    void foo();
    void bar();
    
    void test(bool cond)
    {
        int a; // uninitialized
    
        if (cond)
        {
            a = 24;
        }
    
        if (a == 24)
        {
            foo();
        }
        else
        {
            bar();
        }
    }
    

    What is the result of calling the above function with true? What about with false?

    test(true) will cleary call foo().

    What about test(false)? If you answer: "Well it depends on what garbage value is in variable a, if it is 24 it will call foo, else it will call bar" Then you are completely wrong.

    If you call test(false) the program accesses an uninitialized variable and has Undefined Behavior, it is an illegal path and so the compilers are free to assume cond is never false (because otherwise the program would be illegal). And surprise surprise both gcc and clang with optimizations enabled actually do this and generate this assembly for the function:

    test(bool):
            jmp     foo()
    

    So don't do this! Never access uninitialized variable! It is undefined behavior and it's much much worse than "the variable has some garbage value". Furthermore, on your system could work as you expect, on other systems or with other compiler flags it can behave in unexpected ways.

    What are the dangers of defining uninitialized variables if I make sure I always initialize them later, before accessing them?

    Well, the program is correct from this respect, but the source code is prone to errors. You have to mentally burden yourself with always checking if somewhere you actually initialized the variable. And if you did forget to initialize a variable finding the bug will be difficult as you have a lot of variables in your code who are defined uninitialized.

    As opposed, if you always initialize your variables you and the programmers after you have a much much easier job and ease of mind.

    It's just a very very good practice.

    0 讨论(0)
  • 2021-01-18 21:13

    You have not included the source so we have to guess about why it happens, and I can see possible reasons with different solutions (except just zero-initializing everything):

    1. You don't initialize at the start of the constructor, but you combine member initialization with some other code that calls some functions for the not fully initialized object. That's a mess - and you never know when some functions will call another function using some non-initialized member. If you really need this, don't send in the entire object - but only the parts you need (might need more refactoring).
    2. You have the initialization in an Init-function. Just use the recent C++-feature of having one constructor call another instead.
    3. You don't initialize some members in the constructor, but even later. If you really don't want to initialize it having a pointer (or std::unique_ptr) containing that data, and create it when needed; or don't have it in the object.
    0 讨论(0)
  • 2021-01-18 21:13

    It's a safety measure to not allow uninitialized variables, witch is a good thing, but if you are sure of what you are doing and you make sure your variables are always initialzed before use, you can turn this off, right click on your project in solution explorer -> properties -> C/C++ -> SDL checks, this should be marked as NO. It comes as YES by default.

    Note that these compile-time checks do more than just check for unitialized variables, so before you turn this off I advise reading https://docs.microsoft.com/en-us/cpp/build/reference/sdl-enable-additional-security-checks?view=vs-2019

    You can also disable a specific warning in you code using warning pragma

    Personally I keep these on because IMO in the tradeoff safety/annoyance I prefer safety, but I reckon that someone else can have a different opinion.

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