YotKay
YotKay

Reputation: 1207

gcc shows 0 for a struct's property but clang shows a different value

Consider this code:

#include <iostream>
using namespace std;

struct Z
{
    Z() { cout << "ctor Z" << endl; }
};

struct A
{
    A() = default;
    A(int xx) : x(xx) {}
    int x;
    Z z;
};

int main()
{
    A a;
    cout << "a.x = " << a.x << endl;
}

Compiled with newest GCC it prints:

ctor Z
a.x = 0

But compiled with newest Clang it prints:

ctor Z
a.x = 4198800

Why? Can someone explain this? Does GCC initiates the 'x' prinitive value while it doesn't have to do it? Or, maybe Clang doesn't initiante the 'x' with 0, while it should do it?

The same happens when I remove my constructors from the "A" struct, so it is not a matter of the constructor being marked as 'default' or something like that. To put this simply - one compiler generates code which calls constructors of its members being class objects, and also members being primitives. The other compiler runs constructor of only the class objects members.

Why?

Upvotes: 0

Views: 345

Answers (3)

tadman
tadman

Reputation: 211590

You need to initialize x in every constructor, not just one of them. Using the default constructor leaves it uninitialized. GCC might zero it out, or it might be zeroed out when the process is launched. clang is doing it right here by having garbage data; it shows there's a bug.

You could fix this with:

A(int xx = 0) : x(xx) {}

Where the other constructor is no longer required since you've provided a default value.

Upvotes: 3

Amadeus
Amadeus

Reputation: 10655

x is being default initialized. Looking at http://en.cppreference.com/w/cpp/language/default_initialization

Default initialization is performed in three situations:

1) when a variable with automatic, static, or thread-local storage duration is declared with no initializer;

2) when an object with dynamic storage duration is created by a new-expression with no initializer or when an object is created by a new-expression with the initializer consisting of an empty pair of parentheses (until C++03);

3) when a base class or a non-static data member is not mentioned in a constructor initializer list and that constructor is called.

The effects of default initialization are:

  • if T is a non-POD (until C++11) class type, the constructors are considered and subjected to overload resolution against the empty argument list. The constructor selected (which is one of the default constructors) is called to provide the initial value for the new object;

  • if T is an array type, every element of the array is default-initialized;

  • otherwise, nothing is done: the objects with automatic storage duration (and their subobjects) are initialized to indeterminate values.

Upvotes: 2

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385144

It shouldn't be a surprise that different compilers produce different code. Otherwise there would only be one compiler.

The differences between them are particularly noticeable in the way they treat instances of undefined behaviour, such as reading the indeterminate "value" of an uninitialised object (e.g. A::x here).

It's both extremely complicated and utterly pointless to rationalise about why specific compilers specifically resulted in specific values here, because there are so very many possible explanations, all of which could change the next time you hit "compile". It's easier to discuss when an implementation fills a memory space with e.g. 0xCCCCCCCC in debug mode, so that you can see when you forgot to initialise something. That hasn't happened in either case here, though.

Upvotes: 2

Related Questions