为什么使用/ Og和/ GL标志会发生这种访问冲突,并通过引用传递?

Meh*_*dad 9 c++ stl access-violation undefined-behavior visual-c++

当(且仅当)我编译我的程序与/Og /GL标志使用Windows Server 2003 DDK C++编译器(这是对WDK 7.1和Visual Studio 2010的!),我得到一个访问冲突,当我运行以下命令:

#include <algorithm>
#include <vector>

template<typename T> bool less(T a, T b) { return a < b; }

int main()
{
    std::vector<int> s;

    for (int i = 0; i < 13; i++)
        s.push_back(i);

    std::stable_sort(s.begin(), s.end(), &less<const int&>);
}
Run Code Online (Sandbox Code Playgroud)

当我将最后一行更改为时,访问冲突消失了

    std::stable_sort(s.begin(), s.end(), &less<int>);
Run Code Online (Sandbox Code Playgroud)

- 换句话说,当我让我的项目被复制而不是仅仅被引用时它会消失.

(我没有任何形式的多线程.)

为什么会发生这样的事情?我通过路过来调用一些未定义的行为const &吗?



编辑:

我只是尝试使用Windows XP DDK(那是C:\WinDDK\2600),我得到了:

error LNK2001: unresolved external symbol
    "bool __cdecl less(int const &,int const &)" (?less@@YA_NABH0@Z)
Run Code Online (Sandbox Code Playgroud)

但是当我将它从模板更改为常规函数时,它神奇地适用于两个编译器!

我怀疑这意味着我在使用DDK编译器获取模板化函数的地址时发现了一个错误.任何想法,如果可能是这种情况,或者如果它是一个我不知道的不同的角落案例?

Mic*_*urr 5

我尝试使用Windows Server 2003 DDK SP1安装(非SP1 DDK目前不可用).这使用cl.exe版本13.10.4035 for 80x86.它似乎与您找到的问题相同.

如果你通过一个调试器的代码(这是通过使用生成的.cod文件一起下了一个更容易一些步骤/FAsc选项),你会发现,less<int const &>()功能预计将与指针的被称为int传入值eaxedx.但是,调用less<int const&>()(命名_Insertion_sort_1<>())的函数会调用它来传递堆栈上的指针.

如果将模板化less函数转换为非模板化函数,它希望参数在堆栈上传递,因此每个人都很高兴.

有点更多的利益是当你改变会发生什么less<const int&>less<int>代替.没有崩溃,但也没有任何事情被排序(当然,您需要更改程序以使用未排序的矢量开始实际看到此效果).这是因为当你改变less<int>less功能不再提领的指针-它预计寄存器传递的实际int类型(ecx并且edx在这种情况下).但没有指针解除引用意味着没有崩溃.但是,调用者_Insertion_sort_1仍然传递堆栈上的参数,因此执行的比较less<int>与向量中的值无关.

这就是发生了什么,但我真的不知道根本原因是什么 - 正如其他人所提到的,它看起来像是与优化相关的编译器错误.

由于该错误已明显得到修复,因此报告它显然没有意义(该版本的DDK中的编译器对应于接近VS 2003/VC 7.1的内容).

顺便说一下 - 我无法让你的例子完全干净地编译 - 为了让它完全构建,我必须包含它bufferoverflowu.lib来获取链接检查的东西,甚至连接器也抱怨"多个".rdata '找到具有不同属性的部分".我似乎记得这是一个可以安全忽视的警告,但我真的不记得了.我不认为其中任何一个都与这个bug有关.