SIGFPE с неупорядоченной картой std - PullRequest
0 голосов
/ 15 января 2019

Ниже приведено простое приложение, которое вызывает SIGFPE для меня, если я раскомментирую упомянутую строку в файле main.cc.

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;
}

Был указатель, связанный с этой проблемой в https://stackoverflow.com/a/36406774/3884862, но я не мог понять, почему это происходит.

Я компилирую его с помощью

g ++ -std = c ++ 14 main.cc table_provider.cc -o test

g ++ (Ubuntu 5.4.0-6ubuntu1 ~ 16.04.11) 5.4.0 20160609

Ответы [ 2 ]

0 голосов
/ 15 января 2019

У вас есть статический порядок инициализации фиаско .

Не помещайте определения в файл header , так как это приведет к тому, что каждая единица перевода будет иметь собственную копию переменных, определенных в заголовочный файл.

Это означает, что gTable1, возвращаемый getConfigTable, будет отличаться от gTable1, определенного в файле main.cc. И этот другой gTable1, возможно, не был инициализирован, когда вы используете его.

Решение состоит в том, чтобы поместить глобальные переменные в единичную единицу перевода (исходный файл). Или, что еще лучше, вообще не используйте глобальные переменные.

0 голосов
/ 15 января 2019

Этот код страдает от статического порядка инициализации фиаско .Единица перевода gTable1 в table_provider.cc может не инициализироваться при инициализации единицы перевода gName в main.cc.Обратите внимание, что, поскольку gTable1 - это переменная static, объявленная в заголовочном файле, каждая единица перевода будет иметь отдельный экземпляр.Так что прямой доступ к нему и использование getConfigTable будут ссылаться на различные объекты.

...