İbrahim
İbrahim

Reputation: 1021

C++: The strange behavior when initialize member data

I've encountered a strange behavior about C++17 static inline member data.
There is Implementation abstract class:

class Implementation
{
public:
  virtual void call() = 0;
};

There are Example and AnotherExample classes that implement the abstract class:

class Example : public Implementation
{
public:
  void call() override
  {
    cout << "Called Example::call function!" << endl;
  }
};

class AnotherExample : public Implementation
{
public:
  void call() override
  {
    cout << "Called AnotherExample::call function!" << endl;
  }
};

Finally there is Implementer class to use Example and AnotherExample classes:

class Implementer
{
private:
  static inline Implementation* example = unique_ptr<Example>(new Example).get(); // or make_unique<Example>().get()
  static inline Implementation* another_example = new AnotherExample;
public:
  static Implementation* get_example(bool flag)
  {
    // This function returns example object if flag is true otherwise another_example object.
    if (flag)
      return example;
    else
      return another_example;
  }
};

Using:

Implementer::get_example(true)->call(); // This expect to return example.
Implementer::get_example(false)->call(); // This expect to return another_example.

We expect to see this:

Called Example::call function!
Called AnotherExample::call function!

but we see this:

Called AnotherExample::call function!
Called AnotherExample::call function!

I don't understand it. How does example object get the value of another_example object?

Edit: We can get desired output if we change

static inline Implementation* example = unique_ptr<Example>(new Example).get();

to

static inline unique_ptr<Implementation> example = unique_ptr<Example>(new Example);

Upvotes: 2

Views: 88

Answers (1)

bobah
bobah

Reputation: 18864

The unique_ptr<Example>(new Example).get() would destroy the new Example instance as soon as the result of get() gets assigned (thanks @JVApen for correcting).

From that point on a whole lot of strange things may happen.

For instance, the object allocated by new AnotherExample can (and most probably will) be placed to the same memory where the first one was, and the first pointer would suddenly point to a valid live object again.

Not sure if this qualifies as an ABA phenomenon, but what happens is very similar -- you think you are looking at A, but it's a different A.

I'd first clean it up under Valgrind or ASAN.

Coliru sandbox here

Upvotes: 5

Related Questions