header 中的 const inline std::map 在退出时导致堆损坏
const inline std::map in header causes heap corruption at exit
我想在 header 中使用 const std::map
作为将在其他 cpp-s 中使用的全局常量。所以我声明为:
// header.h
const inline std::map<int, int> GlobalMap = { {1, 2}, {3, 4} };
但是,如果我将此 header 包含在多个 cpp-s 中,堆损坏会在退出时发生,因为多个析构函数 运行 用于同一内存地址。
我一直认为内联常量是全局 non-literal 常量的灵丹妙药。我已经将 global std::string
-s 声明为 const
内联并且它工作得很好。
所以我的问题是:
- 为什么要这样做?它不会使
const
内联很容易出错吗?
- 如何在 C++17 中正确声明全局
const std::map
?我如何确保只创建一个全局 object?
编辑:
我可以在 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;
}
关于你在 C++17 中的第二个问题,你可以应用此修复程序,以便在整个项目中只有一个地图实例
struct Globals
{
static inline const std::map<int, int> Map = { {1, 2}, {3, 4} };
};
或者您可以使用 extern
:
my_global.h
#ifndef my_global_h
#define my_global_h
#include <map>
extern const std::map<int, int> GlobalMap;
#endif /* my_global_h */
my_global.cpp
#include "my_global.h"
const std::map<int, int> GlobalMap = { {1, 2}, {3, 4} };
但我认为第一个解决方案要好得多。
P.S. 我已将您的代码行放入一个头文件中,然后将该头文件包含到多个 *.cpp 中,我的程序已编译并退出没有错误, GlobalMap
的地址在所有翻译单元中都是相同的。
所以我同意@Mikhail 的观点,如果您向我们提供一些重现案例,那就太好了。
这看起来像一个 Visual Studio 错误:https://developercommunity.visualstudio.com/t/static-inline-variable-gets-destroyed-multiple-tim/297876
在发布时,该错误的状态为“已关闭 - 优先级较低”,即尚未修复。
来自the comment of the Microsoft representative:
If you still face this issue in our latest version, please report it as a new problem.
所以我建议用重现案例提交一个新问题。
我想在 header 中使用 const std::map
作为将在其他 cpp-s 中使用的全局常量。所以我声明为:
// header.h
const inline std::map<int, int> GlobalMap = { {1, 2}, {3, 4} };
但是,如果我将此 header 包含在多个 cpp-s 中,堆损坏会在退出时发生,因为多个析构函数 运行 用于同一内存地址。
我一直认为内联常量是全局 non-literal 常量的灵丹妙药。我已经将 global std::string
-s 声明为 const
内联并且它工作得很好。
所以我的问题是:
- 为什么要这样做?它不会使
const
内联很容易出错吗? - 如何在 C++17 中正确声明全局
const std::map
?我如何确保只创建一个全局 object?
编辑: 我可以在 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;
}
关于你在 C++17 中的第二个问题,你可以应用此修复程序,以便在整个项目中只有一个地图实例
struct Globals
{
static inline const std::map<int, int> Map = { {1, 2}, {3, 4} };
};
或者您可以使用 extern
:
my_global.h
#ifndef my_global_h #define my_global_h #include <map> extern const std::map<int, int> GlobalMap; #endif /* my_global_h */
my_global.cpp
#include "my_global.h" const std::map<int, int> GlobalMap = { {1, 2}, {3, 4} };
但我认为第一个解决方案要好得多。
P.S. 我已将您的代码行放入一个头文件中,然后将该头文件包含到多个 *.cpp 中,我的程序已编译并退出没有错误, GlobalMap
的地址在所有翻译单元中都是相同的。
所以我同意@Mikhail 的观点,如果您向我们提供一些重现案例,那就太好了。
这看起来像一个 Visual Studio 错误:https://developercommunity.visualstudio.com/t/static-inline-variable-gets-destroyed-multiple-tim/297876
在发布时,该错误的状态为“已关闭 - 优先级较低”,即尚未修复。
来自the comment of the Microsoft representative:
If you still face this issue in our latest version, please report it as a new problem.
所以我建议用重现案例提交一个新问题。