【问题标题】:ODR bug in MSVC?MSVC 中的 ODR 错误?
【发布时间】:2016-02-06 07:34:06
【问题描述】:

当使用 MSVC(VS 2015)编译时,此程序打印 1 1 而不是 1 2

f1.cpp:

#include <functional>

static std::function<int ()> helper() {
    struct F { int operator()() { return 1; } };
    return F();
}

std::function<int ()> f1() { return helper(); }

f2.cpp:

#include <functional>

static std::function<int ()> helper() {
    struct F { int operator()() { return 2; } };
    return F();
}

std::function<int ()> f2() { return helper(); }

main.cpp:

#include <functional>
#include <iostream>

std::function<int ()> f1();
std::function<int ()> f2();

int main() {
    std::cout << f1()() << " " << f2()() << "\n";
}

好像F 的不同定义正在破坏ODR。但是本地类不应该是不同的吗?有趣的是,如果我们将 F 替换为 lambda 函数,则不会发生冲突。

那么这是编译器错误还是我误解了单一定义规则?

【问题讨论】:

  • MSVC 遇到这样的错误有点疯狂。如果您删除 static 并使用未命名的命名空间,它甚至会出错。
  • 当你使用两个独立的 cout 而不是一个时会发生什么?
  • 你确定吗?在 MSVC 14.0 中,如果将 helper() 放在匿名命名空间中,那么冲突就会消失。
  • 我想知道这是否是由于COMDAT folding 攻击你可以使用/opt:noicf 关闭它
  • 获得与/link /opt:noicf 相同的行为。我假设折叠只适用于具有相同定义的函数,这里不是这种情况。

标签: c++ visual-c++ one-definition-rule


【解决方案1】:

这显然是 MSVC 中的一个错误,因为所有类型都是唯一的。也许对于在某个函数内定义的结构(在这种情况下为helper),MSVC 在内部将它们视为定义为helper::F,而如果帮助器是静态的,它应该做类似f1_cpp::helper::F 的事情。 结果,在链接时,链接器会看到两个同名的内联函数并将它们合并为一个。

如果您对1 1 不满意,很可能通过重新排序输入文件可以得到2 2 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-13
    • 2014-12-26
    • 1970-01-01
    • 1970-01-01
    • 2010-10-18
    • 2020-05-21
    相关资源
    最近更新 更多