c++visual-studio-2017c++17inline-variable

Multiple destruction of an inline variable


Here is a header file containing an inline variable:

// inline.hpp
#pragma once

#include <iostream>

struct Test {
    ~Test() { std::cout << "deleted" << std::endl; }
};

inline const Test test;

...included into two .cpp files:

// usage.cpp
#include "inline.hpp"
// main.cpp
#include "inline.hpp"
auto main() -> int { return 0; }

This program prints "deleted" twice which is unexpected. I thought there was only a single instance of every inline variable, so I was expecting only one "deleted".

Is this a bug of the compiler? Or did I do something wrong?

The code is compiled with VS2017.


Solution

  • Is this a bug of compiler?

    As far as I can tell, yes. GCC and Clang, (as well as VS2019 according to comments) print "deleted" only once.

    A non-volatile const inline variable in namespace scope has external linkage. The behaviour that you describe appears to imply internal linkage, which is wrong behaviour from the compiler.

    For completeness, the relevant standard rules (from latest draft, emphasis added by me, bracketed emphasised parts added by me):

    [basic.link]

    A name having namespace scope has internal linkage if it is the name of

    • ... explicitly declared static; [does not apply] or

    • a non-template variable of non-volatile const-qualified type, [applies...] unless

      • ...
      • it is inline or exported, [exception applies] or

    ... A name having namespace scope that has not been given internal linkage above [applies] and that is the name of

    • a variable; [applies] or

    • ...

    has its linkage determined as follows:

    • if the enclosing namespace has internal linkage, the name has internal linkage; [does not apply]

    • otherwise, if the declaration of the name is attached to a named module ... [does not apply]

    • otherwise, the name has external linkage. [applies]