繁体   English   中英

为什么 linker 在链接共享和 static 时不会抱怨多个定义

[英]Why linker does not complain about multiple definitions when linking against shared and static

我最近在我正在开发的代码中遇到了 static 初始化失败的问题。 这让我意识到我缺乏关于链接过程和全局变量初始化的知识,所以我在 cppcon 上发现了这个非常有趣的关于全局变量、链接以及将 static 库嵌入共享和同时链接的可能问题(与全局变量定义)。 基本上说的是,当具有以下结构时:

//static.hpp
#pragma once

#include <string>

extern std::string globalString;

//static.cpp
#include "static.hpp"

std::string globalString;

//shared.hpp
#pragma once

#include "static.hpp"
#include <string>

std::string& getGlobalString();

//shared.cpp
#include "shared.hpp"
#include "static.hpp"

std::string& getGlobalString(){
  return globalString;
}

//main.cpp
#include "static.hpp"
#include "shared.hpp"
#include <iostream>

int main(){
    std::cout << "Global variable: " << globalString <<  std::endl;
    std::cout << "Global var acccesed through shared lib: " << getGlobalString() << std::endl;
    return 0;
}

所有编译:

clang++ -c -std=c++14 -fpic static.cpp
clang++ -c -std=c++14 -fpic shared.cpp
clang++ -c -std=c++14 main.cpp
ar rsc libstatic.a static.o
clang++ -shared -o libshared.so shared.o -L./ -lstatic
clang++ -L./ -Wl,-rpath=./ main.o -lstatic -lshared

由于多次调用同一个 object 的构造函数和析构函数,导致分段错误。 这是令人惊讶的,因为我认为每个 object 构造函数都将被调用一次是不变的!

  • 关于多次调用构造函数/析构函数的标准是什么?
  • 如果在这种情况下,我将 static 的全局嵌入到 main.o 和 libshared.so 中,这是否意味着有一个定义的规则被打破了? 为什么 linker 在链接 main 时没有抱怨第二个定义可用?
  • 当在单独的翻译单元中至少有两个全局时,建立构造和销毁顺序的建议方法之一是在第一次使用时进行初始化。 然而,据我所知,这只能确保施工顺序。 毁灭令呢? 如何控制?

这是令人惊讶的,因为我认为每个 object 构造函数都将被调用一次是不变的!

在正确构造的二进制文件中,这是正确的。 在具有 ODR 违规的二进制文件中不一定正确。

关于多次调用构造函数/析构函数的标准是什么?

该标准规定,在正确构造的程序中,构造函数/析构函数只被调用一次。 在违反 ODR 的程序中,任何事情都可能发生(未定义的行为)。

如果在这种情况下,我将 static 的全局嵌入到 main.o 和 libshared.so 中,这是否意味着有一个定义的规则被打破了?

是的。

为什么 linker 在链接 main 时没有抱怨第二个定义可用?

就 linker 而言,你的程序没有问题。 从 linker 的角度来看,在 static 和共享库中定义一个全局是完美的。 另请参阅此答案

当在单独的翻译单元中至少有两个全局时,建立构造和销毁顺序的建议方法之一是在第一次使用时进行初始化。 然而,据我所知,这只能确保施工顺序。

正确的。 这是针对不同问题的解决方案:两个全局变量 A 和 B 在单独的翻译单元中定义。

你没有那个问题,你有一个完全不同的问题(违反 ODR)。

毁灭令呢? 如何控制?

在正确构造的程序中,破坏顺序保证与构造顺序相反。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM