0

Do all "real" C++ compilers don't have default initialization with zeros of built-in types? I'm asking 'cos I've found on-line compilers that is claimed to be gcc, and it does zero initialization of built-in types

int h=6548;
   for (int i; i < 10; ++i) {
    cout<<i<<"\n";
}

for this code its output is

0
1
2
3
4
5
6
7
8
9
user207421
  • 305,947
  • 44
  • 307
  • 483
Borrimoro
  • 529
  • 3
  • 9
  • 19
  • 1
    MVS's C++ compiler, for example, doesn't guarantee that all types will be initialized with 0 (on number types) or a 0-string. – Iosif Murariu Jul 24 '13 at 09:57
  • 2
    It's an UB. So, compiler specific. – m0nhawk Jul 24 '13 at 09:59
  • All gcc versions I tested on a Mac initialize to zero and even initialize memory allocated by `malloc()` and friends with 0. – arne Jul 24 '13 at 09:59
  • 2
    Example: http://coliru.stacked-crooked.com/view?id=345d62704a3ce9a9f8464807dabc2f94-80c199070668c72f0a5e12e38239d72b. Notice how there's no output *at all*. This code has undefined behaviour, meaning that the choices are not limited to initialising or not to zero: the compiler can choose to do anything else, like, in this case, throwing away the whole loop as garbage. – R. Martinho Fernandes Jul 24 '13 at 10:00
  • 1
    But, `static int i` is **guaranteed** to by zero initialized. – m0nhawk Jul 24 '13 at 10:01
  • Possible duplicate of http://stackoverflow.com/questions/2218254/variable-initialization-in-c – Sanyam Goel Jul 24 '13 at 10:01
  • @SanyamGoel no, I'm not asking about C++ standard, question is about compilers realization – Borrimoro Jul 24 '13 at 10:05
  • Then you should specify which compilers you are asking about. – juanchopanza Jul 24 '13 at 10:06
  • @juanchopanza in my first sentence – Borrimoro Jul 24 '13 at 10:07
  • @Borrimoro also please go through all the answers in that post You will see people have described how different compilers behave – Sanyam Goel Jul 24 '13 at 10:07
  • 2
    "real compilers" is not nearly good enough. Go on, make an effort. – juanchopanza Jul 24 '13 at 10:12
  • @arne Are you sure? Does the documentation say so? And how did you test it? (Remember, memory freshly obtained from the OS _will_ generally be initialized to `0`. You don't want to unexpectedly find confidential data from the previous process which used the memory in it.) – James Kanze Jul 24 '13 at 10:37
  • @JamesKanze: I've only extensively coded on Mac a few years ago, during university, so I can't say how it is now. But I know for sure that on the Linux boxes at work, memory is NOT 0-initialized on `malloc()`. – arne Jul 24 '13 at 10:41

5 Answers5

2

What initialization. In your example, accessing i is undefined behavior, since it wasn't initialized. Some compilers do initialize it, at least in debug mode, but generally with something like 0xDEADBEEF or 0xCCCCCCCC, so that you can easily recognize in a debugger that you're accessing uninitialized memory (and so that the program is likely to crash if you use it as a pointer), but this is not required.

The only time built-in types are implicitly initialized is when they have static storage duration: variables defined at namespace scope (include static class members), or local variables which have been declared static.

You don't show the context of your code, but if it is directly in main, or in the first function called from main, int i will be the first use of this actual memory. And the OS probably will have set it to 0, for security reasons. You might want to try something like:

void scribble()
{
    int x = 0x12345678;
}

void testit()
{
    for ( int i; i < 10; ++ i ) {
        std::cout << i << '\n';
    }
}

int
main()
{
    scribble();
    testit();
    return 0;
}

The call to std::operator<<( std::ostream&, char const* ) is might have left something different from 0 in this particular memory cell. (Or the compiler has optimized it out. Try this with all optimization turned off.) Neither g++ nor VC++ initialize the i in testit.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • Not the best question, but a very comprehensive explanation of what happened. Especially like the scribble() part. Though on my g++ 4.9.2, I believe unused x is optimized away and the whole int i loop is taken away altogether. – Shi B. Dec 21 '15 at 16:20
2

Whether or not the values are initialized is undefined behaviour and implementation dependant. You must not rely on that.

1. C++11, 8.5/11

If no initializer is specified for an object, the object is default-initialized; if no initialization is performed, an object with automatic or dynamic storage duration has indeterminate value. [ Note: Objects with static or thread storage duration are zero-initialized, see 3.6.2. —end note ]

If you use int i; this results in an uninitialized integer which has "indeterminate value"! You can't predict what will happen if you access it's value.

2. C++11, 8.5/10

An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.

If you use int i = int(); you have a value-initialized i. Now, what is value-initialized?

3. C++11, 8.5/7

To value-initialize an object of type T means:

  • [...] (some options where T may be class or array type)
  • otherwise, the object is zero-initialized.

Ok now we know that int i = int(); means having i=0.

Be aware of the following:

Note: Since () is not permitted by the syntax for initializer,

    X a();

is not the declaration of a value-initialized object of class X, but the declaration of a function taking no argument and returning an X.

Emphasis on standard quotes are mine.

Community
  • 1
  • 1
Pixelchemist
  • 24,090
  • 7
  • 47
  • 71
1

Both the C and C++ standards are VERY clear that there is only one kind of memory that is initialize, and that is the memory for static storage.

Variable with static storage duration are guaranteed to be zero (that aren't initialized or have a constructor). Everything else is "uninitialized", which means "you don't know what it will be" - and one of the options is of course that it is zero.

All other variables are almost guaranteed to not be zero, at least under some circumstances - and it may well be that you can't find those circumstances with a simple test program.

For example, malloc (or new) memory is often zero for "virgin" memory, but fill it with something, then free it and use it again, and it's no longer zero.

Variables on the stack almost inevitably will have different values depending on what the previous call was (and thus, what stuff got put on the stack in the previous function that the code visited).

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • Your first statement applies here, but it is false. There are three cases where C++ ensures initialization: all variables with static lifetime are zero initialized, all variables with explicit initialization are initialized according to the explicit initialization, and all variables of a type with a constructor will have the constructor called. Of course, he doesn't have any explicit initialization, and `int` doesn't have any constructors, so the only consideration is the first, but that's only in this case. – James Kanze Jul 24 '13 at 10:15
  • On the other hand, if his code is in main, there will have been no previous calls, and the OS will probably have cleared the memory before assigning it to his process, so he will see `0` in that case. (Unless the compiler does otherwise: there debugging options for VC++, for example, which will ensure that it is filled with some standard trash value, so that you can recognized uninitialized memory in the debugger.) – James Kanze Jul 24 '13 at 10:28
  • @JamesKanze: Updated second paragraph to cover initialized/constructed types. As to `main()` having virgin memory for stack - that may be the case, but there is initialization of global objects before `main`, which means that you can have quite a bit of call-stack "action" before `main` is actually called (in compilers that doesn't add the global construction inside `main`, that is). – Mats Petersson Jul 24 '13 at 10:35
  • Good point about the static initializers. There will be at least those for `std::cin`, etc. At any rate, I think we agree that you can't count on 0, except for variables with static lifetime, and if he's seeing 0, it's more by chance than because his compiler is initializing local variables. – James Kanze Jul 24 '13 at 10:53
0

It may depend on compilers to compilers, but it is better to make initialization a habit because you may not know which old compiler you may end up with and you may get screwed up by using the uninitialized garbage values.... Another compiler is http://codepad.org/ which also initializes on its part..

Saby
  • 718
  • 9
  • 29
  • 1
    "new compilers"? "old compilers"? This is not about new vs old. Clang is probably the newest compiler around, and doesn't do any initialisation to anything. It just tosses out the code as the garbage it is. Just to be clear on this, *it doesn't give you uninitialised garbage values*. It just gives you one big FU and ignores your buggy code outright. – R. Martinho Fernandes Jul 24 '13 at 10:07
  • I mean new versions of compilers....I was not aware of Clang anyways...New Learning...But I think it is better to initialize on our part everytime... – Saby Jul 24 '13 at 10:10
  • @Saby I don't know of any compiler which initializes non-static local variables when optimization is turned on. Regardless of the version. – James Kanze Jul 24 '13 at 10:12
  • @Saby I mean that too. I am talking about the *newest* version of the *newest* compiler. – R. Martinho Fernandes Jul 24 '13 at 10:15
  • @James: Those are online compilers like http://codepad.org/. In http://www.compileonline.com/ , it claims to be a GCC compiler and it initializes 0 value for non static local variables... – Saby Jul 24 '13 at 10:16
  • @Saby I couldn't even get your code to compile there. I get the error messages "warnings being treated as errors" and "warning: 'i' is used uninitialized in this function". And g++ definitely does _not_ initialize local variables. – James Kanze Jul 24 '13 at 10:34
  • @JamesKanze: Just compile the following code in http://www.compileonline.com/ and the code is : #include using namespace std; int main() { int i; cout< – Saby Jul 24 '13 at 10:35
  • @Saby That's not the link I had earlier. With that compiler, it does compile. And my code (from my answer) definitely shows that the compiler does _not_ initialize local variables. In your example, your instance of `i` just happens to be the first use of that memory cell, and the OS almost certainly does initialize all memory it gives the process to 0, for security reasons. – James Kanze Jul 24 '13 at 10:42
  • @R.MartinhoFernandes: I apologise for bringing the topic of old/new compiler, it actually varies from Compiler to Compiler, edited my comments accordingly... – Saby Jul 24 '13 at 10:45
  • @Saby Actually, it doesn't. _No_ compiler systematically initializes local variables. Some do have options to do so, but those will normally only be used in debug mode. And the compiler the OP cites doesn't initialize local variables, despite his claims to the contrary; it's just purely by chance that he's seeing 0. – James Kanze Jul 24 '13 at 10:55
  • @JamesKanze: In your above example which you have given above, if you change the code as : int main() { scribble(); cout<< "Hello" << endl; testit(); return 0; } then the output will come as Hello 0 1 2 ... So, can you please explain the reason for this? I don't have so much reputation to add comment on your comments above code, so I am asking it here to clear my doubts on this. – Saby Jul 25 '13 at 07:59
  • @Saby The code accesses a variable which wasn't initialized. It's undefined behavior, so you can't count on anything. What happens in practice is that the variable "inherits" the bits that were there previously. In the case of `testit`, whatever the previously called function left on the stack. Which is usually unpredictable; I have no idea what `std::operator<<( std::ostream&, char const* )` might leave on the stack. – James Kanze Jul 25 '13 at 08:20
  • @JamesKanze: Ok .. thnx James for your reply, I understood. It is really a waste and meaningless to predict on undefined values. – Saby Jul 25 '13 at 08:23
0

NO one compiler initialize with zero. I can say that somehow you were lucky. Try this in online compiler you gave.

for(int i;i < 10; ++i)   
{  
    int a;  
    cout << a << endl;  
    a = 1;  
}

And you will see that first time a is equal 0 and next 9 times it's equal 1.

Straticiuc Vicu
  • 102
  • 3
  • 12