热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

为什么此代码链接在英特尔编译器2015而非英特尔编译器2018?

如何解决《为什么此代码链接在英特尔编译器2015而非英特尔编译器2018?》经验,谁能帮忙解答一下?

我的团队最近从2015英特尔编译器(并行工作室)升级到2018年版本,我们遇到了一个链接器问题,每个人都在撕扯他们的头发.

我有以下类(为了简洁而适度编辑)来处理子进程的包装和相关的文件描述符以便与它们交谈:

class SubprocWrapper
{
public:
    static const int PASSTHRU_FD = 0;
    static const int MAKE_PIPE = -1;

    typedef std::map EnvMapType;

    static EnvMapType getMyEnv();

    SubprocWrapper(
        int stdin_fd_req,
        int stdout_fd_req,
        int stderr_fd_req,
        const std::string & execPath,
        const std::vector & args,
        const std::set & dont_close_fds,
        const EnvMapType * env = 0);
};

然后我用以下代码调用它:

std::string runCmd = "/run/some/file.bin";
std::vector 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(), //dont_close_fds = null means "close all fds"
    &env_vars
);

在2015年和2018年的英特尔编译器上,上面的代码编译得很好.

但是,在2018年的英特尔编译器中,上面的代码无法链接,而在2015年的英特尔编译器中,它链接得很好.

错误似乎是链接器无法找到构造函数符号,因为我得到以下错误:

    SourceFile.o: in function  SourceFile.hh:: undefined reference to 
`SubprocWrapper::SubprocWrapper(int, int, int, std::string const&,
 std::vector > const&,
 std::set, std::allocator > const&,
 std::map,
 std::allocator > > const*)'

请注意,SubprocWrapper类正在编译为.a文件,并静态链接到调用它的代码中.在生成的.a文件上执行nm似乎确认SubprocWrapper构造函数的符号存在,但代码仅链接在2015下,即使原始.a是使用2018编译的.我们已确认正在传入正确的.a文件在链接器行(我们的构建过程没有改变),我们尝试在链接顺序中移动.a无济于事.

在我链接的.a文件上执行nm会显示与构造函数关联的以下签名(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年左右没有改变,所有以前版本的英特尔编译器都使用它很好.

为什么此代码在英特尔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!)

编辑: 这个问题似乎是某种竞争条件.当使用非常大的作业批处理(make -j30)进行编译时,我们在Intel 2015编译器上也注意到了它.问题突然出现,经过进一步检查,我们发现其中一个.o文件是使用符号的KS版本而不是IS2版本编译的.在交换了几个咒骂之后,我们删除了有问题的.o文件并再次编译没有作业批处理(只是make),并且令我们惊讶地发现,编译器这次为该函数生成了一个不同的符号(IS2版本) ).这似乎非常奇怪,因为无论作业批号如何,编译器都应始终生成相同的符号.不幸的是,这种行为不容易重复,因为我们做了一个make clean,并且再次运行了一个高工作批号,却发现它在那个时候工作了.


推荐阅读
author-avatar
流云清动_438
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有