c++ - 链接器何时会在多个定义的符号上出错?

标签 c++ visual-studio-2010

当我在 A.cpp 中有以下代码时 B.cpp没有生成警告或错误,但是 Initializer::Initializer()B.cppA.cpp 中被调用两次不会被调用。

static int x = 0;

struct Initializer
{
    Initializer()
    {
        x = 10;
    }
};

static Initializer init;

由于这违反了单一定义规则并导致未定义的行为,我认为这是完全正常的。但是,当我将构造函数定义移到一个或两个文件中的类声明之外时,如下所示:

static int x = 0;

struct Initializer
{
    Initializer();
};

Initializer::Initializer()
{
    x = 10;
}

static Initializer init;

链接器突然变得足够聪明,可以出错并说出 one or more multiply defined symbols found .这里发生了什么变化,为什么重要?我本以为链接器应该始终能够检测到 ODR 损坏 - 什么情况下它不能检测到?

如果我错了,请有人纠正我,但我的理论是,当您使用模板化代码(定义总是在标题中)时,您最终会在许多编译单元中得到重复的定义。它们碰巧都是相同的,因此链接器是否只选择一个并孤立其他的并不重要,但它不会出错,因为有多个定义或模板不起作用。

最佳答案

您的第二个示例明显且易于诊断是否违反了单一定义规则。它有两个带有外部链接的非内联函数的定义。这对于链接器来说很容易诊断,因为从它所链接的目标文件中包含的函数的名称来看,违规是显而易见的。

您的第一个示例以更微妙的方式打破了单一定义规则。因为在类主体中定义的函数被隐式声明为内联,所以您必须检查函数主体以确定是否违反了一个定义规则

仅出于这个原因,我对您的实现未能发现违规行为(我第一次没有发现)并不感到惊讶。显然,当单独查看一个源文件时,编译器不可能发现违规,但检测违规和链接时间的信息可能实际上并不存在传递给链接器的目标文件。它肯定超出了我期望链接器找到的范围。

关于c++ - 链接器何时会在多个定义的符号上出错?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11095187/

相关文章:

c++ - 从 main 返回时出现段错误(非常简短的代码,没有数组或指针)

C++ 二维动态数组

visual-studio-2010 - 如何将我的 MVC 3 Web 应用程序发布到 IIS7

.net - WiX - 在设置输出中收集非项目程序集

c# - 嵌入资源的名称

c++ - 使用 emplace_back 指向 const 对象的指针

c++ - 重用 move 的容器?

python - OpenCV - 检测矩形或五边形

c++ - 尽管链接到具有导出符号的 .lib 文件,但从托管 C++ 链接到非托管 C++ 时出现链接错误

visual-studio - 从 Visual Studio 的工具栏调用 exe