Моя команда недавно обновилась с Intel Compiler 2015 года (параллельная студия) до версии 2018 года, и у нас возникла проблема с компоновщиком, в которой каждый разрывает свои волосы.
У меня есть следующий класс (умеренно отредактированный для краткости) для обработки обертки подпроцессов и связанных файловых дескрипторов для разговора с ними:
class SubprocWrapper
{
public:
static const int PASSTHRU_FD = 0;
static const int MAKE_PIPE = -1;
typedef std::map<std::string, std::string> EnvMapType;
static EnvMapType getMyEnv();
SubprocWrapper(
int stdin_fd_req,
int stdout_fd_req,
int stderr_fd_req,
const std::string & execPath,
const std::vector<std::string> & args,
const std::set<int> & dont_close_fds,
const EnvMapType * env = 0);
};
Затем я вызываю его следующим кодом:
std::string runCmd = "/run/some/file.bin";
std::vector<std::string> args(2);
args[0] = "-c";
args[1] = runCmd;
SubprocWrapper::EnvMapType env_vars = SubprocWrapper::getMyEnv();
SubprocWrapper subproc(
SubprocWrapper::PASSTHRU_FD,
SubprocWrapper::PASSTHRU_FD,
SubprocWrapper::PASSTHRU_FD,
std::string("/bin/sh"),
args,
std::set<int>(), //dont_close_fds = null means "close all fds"
&env_vars
);
На обоих компиляторах Intel 2015 и 2018, приведенный выше код компилируется просто отлично.
Однако, в компиляторе Intel 2018 года, приведенный выше код не связывается, тогда как в компиляторе Intel 2015 года он очень хорошо связывается.
Ошибка заключается в том, что компоновщик не может найти символ конструктора, поскольку я получаю следующие ошибки:
SourceFile.o: in function <MangledName> SourceFile.hh:<LineNum>: undefined reference to
`SubprocWrapper::SubprocWrapper(int, int, int, std::string const&,
std::vector<std::string, std::allocator<std::string> > const&,
std::set<int, std::less<int>, std::allocator<int> > const&,
std::map<std::string, std::string, std::less<std::string>,
std::allocator<std::pair<std::string const, std::string> > > const*)'
Обратите внимание, что класс SubprocWrapper компилируется в .a файл и статически ставится в код, который его вызывает. Выполнение nm в созданном файле .a подтверждает, что символ для конструктора SubprocWrapper существует, но код только связывает до 2015 года, даже если исходный .a был скомпилирован с 2018 годом. Мы подтвердили, что правильный .a файл передается в на линии компоновщика (наш процесс сборки не изменился), и мы попытались переместить .a вокруг в порядке привязки безрезультатно.
Выполнение nm в файле .a, с которым я ссылаюсь, показывает следующие подписи, связанные с конструктором (разные между lib.a и SourceFile.o):
lib.a:
0000000000001020 T _ZN4beau5posix14SubprocWrapperC1EiiiRKSsRKSt6vectorISsSaISsEERKSt3setIiSt4lessIiESaIiEEPKSt3mapISsSsSA_ISsESaISt4pairIS2_SsEEE
0000000000000084 r _ZN4beau5posix14SubprocWrapperC1EiiiRKSsRKSt6vectorISsSaISsEERKSt3setIiSt4lessIiESaIiEEPKSt3mapISsSsSA_ISsESaISt4pairIS2_SsEEE$$LSDA
0000000000001010 T _ZN4beau5posix14SubprocWrapperC2EiiiRKSsRKSt6vectorISsSaISsEERKSt3setIiSt4lessIiESaIiEEPKSt3mapISsSsSA_ISsESaISt4pairIS2_SsEEE
SourceFile.o:
U _ZN4beau5posix14SubprocWrapperC1EiiiRKSsRKSt6vectorISsSaISsEERKSt3setIiSt4lessIiESaIiEEPKSt3mapISsSsSA_ISsESaISt4pairIKSsSsEEE
Обратите внимание, что два искаженных имени конструктора не совпадают!
Я предполагаю, что код соответствует стандарту, поскольку он компилируется отлично, он просто не связан. Код не изменился, вероятно, 7 лет или около того, и все предыдущие версии компилятора Intel работали с ним просто отлично.
Почему этот код работает в Intel 2015, но не в 2018 году?
Operating system: RHEL 7.4
GCC version: 4.8.5
libstdc++ version: 4.8.5
Intel compiler versions:
2015.3.187 (Works!)
2018.1.163 (Fails to link!)