使用o2标志编译会使程序出现trow访问冲突 我知道这可能是一个曾经的生命问题,但我已经坚持了,我想不出任何可能的问题,我已经用Visual Studio编写了C++代码(在不同的类和文件中大约有500行),而我编译它时没有优化标志(OD),它工作得很好,但是当我尝试使用发布配置(/o2标志用于优化)编译它时,程序会导致访问冲突和崩溃。经过一些调试后,我发现有一个这个值在一个成员函数中发生了变化,但如果指针发生了变化,我看不到调用堆栈中指针的任何直接用途,有人能给出任何建议吗?只有在启用优化时,才出现这种情况的原因是什么

使用o2标志编译会使程序出现trow访问冲突 我知道这可能是一个曾经的生命问题,但我已经坚持了,我想不出任何可能的问题,我已经用Visual Studio编写了C++代码(在不同的类和文件中大约有500行),而我编译它时没有优化标志(OD),它工作得很好,但是当我尝试使用发布配置(/o2标志用于优化)编译它时,程序会导致访问冲突和崩溃。经过一些调试后,我发现有一个这个值在一个成员函数中发生了变化,但如果指针发生了变化,我看不到调用堆栈中指针的任何直接用途,有人能给出任何建议吗?只有在启用优化时,才出现这种情况的原因是什么,c++,visual-studio-2010,optimization,assembly,access-violation,C++,Visual Studio 2010,Optimization,Assembly,Access Violation,我不知道这是否对您有帮助,但当我使用优化进行编译时,我可以看到在我的第一个函数调用的末尾添加了一个汇编指令pop ebp我不知道这个指令做什么,但不管它是什么,这就是指针更改的地方 我在尝试使用反汇编程序进行调试时发现了一些新情况,导致问题的函数中有13条push指令,只有10条pop指令(该问题是由ret指令之前的最后一条pop指令引起的),是否正常?(我正在计算被调用函数中的所有push、pop指令。)因为您说this指针突然改变了值,这让我相信这与堆损坏有关。另一方面,既然您说这与优化的代

我不知道这是否对您有帮助,但当我使用优化进行编译时,我可以看到在我的第一个函数调用的末尾添加了一个汇编指令
pop ebp
我不知道这个指令做什么,但不管它是什么,这就是指针更改的地方


我在尝试使用反汇编程序进行调试时发现了一些新情况,导致问题的函数中有13条
push
指令,只有10条
pop
指令(该问题是由
ret
指令之前的最后一条pop指令引起的),是否正常?(我正在计算被调用函数中的所有push、pop指令。)

因为您说this指针突然改变了值,这让我相信这与堆损坏有关。另一方面,既然您说这与优化的代码有关,那么它也可能与堆栈有关。优化器所做的一件事是,它删除堆栈上未使用的变量,这些变量永远不会被访问

这实际上意味着,当您不是在优化模式下编译时,堆栈上会出现更多的变量,从而使内存布局有所不同,并在某种意义上为堆栈添加更多内存空间,这可能会对软件如何响应(例如堆栈溢出)产生巨大影响

如果存在从未使用过的局部变量,则程序不关心是否损坏了从未使用过的局部变量的内存。只有当你破坏了你实际使用的内存,当它成为一个问题时

您可以告诉编译器使用不同的警告级别(如果我没有弄错的话,有四个)。如果使用最高值,则警告将被视为编译器错误,这将停止编译过程。通过这种方式,您可以注意到在优化代码时将删除的局部变量,从而使您更接近实际问题。开始搜索代码的这些区域


我还建议您删除代码并进行测试,只是为了排除有问题的代码所在的位置,然后逐步深入研究并解决问题。当您没有任何信息时,您必须从头开始(程序的主循环),并尝试隔离和排除部分正常工作的代码。“如果我注释掉这个函数调用,那么它不会崩溃”可能会给你一个提示:)

你看到有优化和没有优化的不同行为的原因是你的代码(无意中)依赖于未定义的行为。如果编译器以一种方式布局数据,那么它正好工作,如果编译器以不同的方式布局数据,那么它就会中断

换句话说,你有一个bug

它可能存在于您已经测试过的代码中,也可能存在于您如何使用该代码中。在任何情况下,正如@Nim在评论中所说的,检查分配到哪里并释放内存。检查你的课程是否遵循三条规则。请确认您的某个地方没有缓冲区溢出。也许,也可以尝试使用不同的编译器来编译它。使用静态分析工具(MSVC有/analyze,Clang有--analyze。在Linux上,Valgrind可能是一个不错的选择)


但不要认为这是一个编译器错误。当然,这些错误确实会发生,但它们通常不是此类错误的来源。几乎在所有情况下,它都是开发人员自己代码中的潜在缺陷。仅仅因为它不是每次都触发,每个编译器标志并不意味着它不存在,也不意味着它是编译器的错误。

这可能是一个问题,甚至在调试版本中也存在,但由于内存布局和被破坏的内容,它可能不会显示出来。首先,我要仔细梳理一下你是如何管理你的记忆的。看看所有的动态分配和释放。当我试图在该函数(以及它调用的所有函数)中调试时,如果程序未经优化编译,则没有内存选项,但我会仔细检查它。此外,我在该函数中使用的每件事都通过多个项目进行测试(它们是我在我的每个项目中使用的一些基类)@Gajet,通常情况下,你会因为几种类型的问题而得到这个类,你已经释放了一些东西并再次访问了它,或者你已经访问了缓冲区之外的部分(检查字符串/数组的使用情况等)在不真正了解代码的情况下,很难说问题出在哪里,我们所能做的就是提供一般性提示。@Gajet,如我所说,在调试模式和优化模式下,内存布局可能会有所不同,因此如果您有缓冲区溢出,例如,在调试模式下,您可能很幸运,因为正在访问的内存仍然可以,但在优化模式下,它可以我遇到了一个无法读取的地址。优化是一个骗局,相信我,编译器不太可能做傻事。。。