带有 std unordered_map 的 SIGFPE
SIGFPE with std unordered map
下面是一个简单的应用程序,如果我在 main.cc.
中取消注释提到的行,它会导致我出现 SIGFPE
config.h
#ifndef SRC_CONFIG_H_
#define SRC_CONFIG_H_
#include <cstdint>
#include <unordered_map>
#include <string>
#include <tuple>
#include <vector>
using ConfigTable_t = std::unordered_map<uint16_t, std::tuple<std::string, std::vector<uint8_t> > >;
static const ConfigTable_t gTable1 {
{ 0x100, std::make_tuple( "table1", std::vector<uint8_t> { 5,5,5,5,5,5 } ) }
};
static const ConfigTable_t gTable2 {
{ 0x200, std::make_tuple( "table2", std::vector<uint8_t> { 0,1,2,3,4,5 } ) }
};
const ConfigTable_t & getConfigTable();
#endif
table_provider.cc
#include "config.h"
const ConfigTable_t & getConfigTable() {
return gTable1;
}
main.cc
#include "config.h"
static const uint16_t gId = 0x100;
// static const std::string gName = std::get<0>(getConfigTable().at(gId)); // <-- Doesn't work
static const std::string gName = std::get<0>(gTable1.at(gId)); // <-- Works
int main() {
return 0;
}
中有一个与此问题相关的指针,但我不明白为什么会这样。
我用
编译
g++ -std=c++14 main.cc table_provider.cc -o test
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
此代码存在 static initialization order fiasco。当您初始化 main.cc
翻译单元中的 gName
时,table_provider.cc
翻译单元中的 gTable1
可能未被初始化。请注意,由于 gTable1
是在头文件中声明的 static
变量,因此每个翻译单元都有一个单独的实例。所以直接访问它和使用getConfigTable
会引用不同的对象。
你有一个 static initialization order fiasco.
不要将定义放在 header 文件中,因为这会导致每个 translation unit 将在头文件中定义自己的变量副本。
这意味着 getConfigTable
返回的 gTable1
将不同于 main.cc
文件中定义的 gTable1
。还有那个 gTable1
在你使用的时候可能还没有初始化。
解决方案是将全局变量放在一个单个翻译单元(源文件)中。或者更好的是,根本没有全局变量。
下面是一个简单的应用程序,如果我在 main.cc.
中取消注释提到的行,它会导致我出现 SIGFPEconfig.h
#ifndef SRC_CONFIG_H_
#define SRC_CONFIG_H_
#include <cstdint>
#include <unordered_map>
#include <string>
#include <tuple>
#include <vector>
using ConfigTable_t = std::unordered_map<uint16_t, std::tuple<std::string, std::vector<uint8_t> > >;
static const ConfigTable_t gTable1 {
{ 0x100, std::make_tuple( "table1", std::vector<uint8_t> { 5,5,5,5,5,5 } ) }
};
static const ConfigTable_t gTable2 {
{ 0x200, std::make_tuple( "table2", std::vector<uint8_t> { 0,1,2,3,4,5 } ) }
};
const ConfigTable_t & getConfigTable();
#endif
table_provider.cc
#include "config.h"
const ConfigTable_t & getConfigTable() {
return gTable1;
}
main.cc
#include "config.h"
static const uint16_t gId = 0x100;
// static const std::string gName = std::get<0>(getConfigTable().at(gId)); // <-- Doesn't work
static const std::string gName = std::get<0>(gTable1.at(gId)); // <-- Works
int main() {
return 0;
}
中有一个与此问题相关的指针,但我不明白为什么会这样。
我用
编译g++ -std=c++14 main.cc table_provider.cc -o test
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
此代码存在 static initialization order fiasco。当您初始化 main.cc
翻译单元中的 gName
时,table_provider.cc
翻译单元中的 gTable1
可能未被初始化。请注意,由于 gTable1
是在头文件中声明的 static
变量,因此每个翻译单元都有一个单独的实例。所以直接访问它和使用getConfigTable
会引用不同的对象。
你有一个 static initialization order fiasco.
不要将定义放在 header 文件中,因为这会导致每个 translation unit 将在头文件中定义自己的变量副本。
这意味着 getConfigTable
返回的 gTable1
将不同于 main.cc
文件中定义的 gTable1
。还有那个 gTable1
在你使用的时候可能还没有初始化。
解决方案是将全局变量放在一个单个翻译单元(源文件)中。或者更好的是,根本没有全局变量。