c++ - 为什么这种访问冲突会发生在/Og 和/GL 标志上,并带有传递引用?

标签 c++ visual-c++ stl access-violation undefined-behavior

当(且仅当)我使用 Windows Server 2003 使用 /Og /GL 标志编译我的程序时 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&>);
}

当我将最后一行更改为

时,访问冲突消失
    std::stable_sort(s.begin(), s.end(), &less<int>);

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

(我没有进行任何类型的多线程。)

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


  • 编译器标志:

      /Og /GL /MD /EHsc
    
  • 链接器标志:(无)

  • 包含环境变量:

      C:\WinDDK\3790.1830\inc\crt
    
  • LIB 环境变量:

      C:\WinDDK\3790.1830\lib\crt\I386;C:\WinDDK\3790.1830\lib\wxp\I386
    
  • 操作系统:Windows 7 x64

  • 平台:32位编译报错(64位运行正确)


编辑:

我刚刚用 Windows XP DDK(即 C:\WinDDK\2600)试了一下,我得到了:

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

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

我怀疑这意味着我发现了一个错误,该错误在使用 DDK 编译器获取模板函数的地址时发生。如果是这种情况,或者这是我不知道的其他极端情况,您有什么想法吗?

最佳答案

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

如果您在调试器中单步执行代码(跟随使用 /FAsc 选项生成的 .cod 文件会更容易一些),您会发现 less<int const &>()函数期望用指向 int 的指针调用传入的值 eaxedx .但是,调用 less<int const&>() 的函数(名为 _Insertion_sort_1<>() )调用它传递堆栈上的指针。

如果你打开模板化的less函数转换为非模板函数,它期望参数在堆栈上传递,所以大家都很高兴。

更有趣的是当你改变 less<const int&> 时会发生什么成为less<int>反而。没有崩溃,但也没有任何排序(当然,您需要更改程序以从未排序的 vector 开始才能真正看到这种效果)。那是因为当你改为 less<int> less函数不再取消引用任何指针 - 它期望实际的 int 值在寄存器中传递(在本例中为 ecxedx)。但是没有指针取消引用意味着没有崩溃。然而,来电者,_Insertion_sort_1 , 仍然在堆栈上传递参数,因此 less<int> 正在执行比较与 vector 中的值无关。

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

由于该错误显然已被修复,因此报告它显然没有意义(该版本的 DDK 中的编译器对应于接近 VS 2003/VC 7.1 的东西)。

顺便说一句 - 我无法让你的示例完全干净地编译 - 为了让它完全构建,我必须包含 bufferoverflowu.lib让堆栈检查内容链接,即使这样链接器也会提示“发现多个具有不同属性的'.rdata'部分”。我似乎记得这是一个可以安全忽略的警告,但我真的不记得了。不过,我认为这些都与错误无关。

关于c++ - 为什么这种访问冲突会发生在/Og 和/GL 标志上,并带有传递引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7237837/

相关文章:

C++ 候选函数不可行?

winforms - Visual Studio Express 2012,没有适用于 C++ 的 Windows 窗体?

c++ - MFC VC++:CMFCButton::SetFaceColor 不更改背景(脸部)颜色

c++ - 最终迭代器递减的应用及其含义

c++ - 需要帮助遍历 STL 列表

c++ - Visual C++ 中的 __PRETTY_FUNCTION__

c++ - 编译代码太快会出错

c++ - 泛化返回基于对象和类方法的可调用函数的函数

c++ - Visual Studio 中的 std::begin 和 std::end 迭代器

c++ - 如何更改 std::priority_queue top() 的值?