const inline std::map in header causes heap corruption at exit

Viewed 239

I want to have const std::map in header as a global constant that will be used in other cpp-s. So I declared it as:

// header.h
const inline std::map<int, int> GlobalMap = { {1, 2}, {3, 4} };

However, if I include this header in multiple cpp-s, heap corruption happens at exit time because multiple destructors are run for the same memory address.

I've always assumed that inline const is a silver bullet for global non-literal constants. I've declared global std::string-s as const inline and it worked just fine.

So my questions are:

  1. Why is this intended to happen? Doesn't it make const inline very error prone?
  2. How do I properly declare global const std::map in C++17? And how can I ensure that only one global object would be created?

EDIT: I can reproduce it on the following project in Visual Studio 2017 (/std:c++17, Debug x86)

file_1.h:

#pragma once
#include <map>

const inline std::map<int, double> GlobalMap = {{1, 1.5}, {2, 2.5}, {3, 3.5}};

void f1();

file_1.cpp:

#include "file_1.h"

void f1()
{
    (void)GlobalMap;
}

main.cpp:

#include "file_1.h"

int main()
{
    f1();
    return 0;
}
2 Answers

In regard to your second question in C++17 you can apply this fix in order to have only one instance of the map across whole project

struct Globals
{
    static inline const std::map<int, int> Map = { {1, 2}, {3, 4} };
};

or you could use extern:

  1. my_global.h

    #ifndef my_global_h
    #define my_global_h
    
    #include <map>
    
    extern const std::map<int, int> GlobalMap;
    
    #endif /* my_global_h */
    
  2. my_global.cpp

    #include "my_global.h"
    const std::map<int, int> GlobalMap = { {1, 2}, {3, 4} };
    

But in my opinion first solution is much better.

P.S. I've put your line of code into a header file and after including that header into more than one *.cpp my program compiled and exits without errors and address of GlobalMap is the same in all translation units. So I agree with @Mikhail that it would be great if you provide us with some repro case.

Related