当前位置:  开发笔记 > 编程语言 > 正文

GCC:程序不适用于编译选项-O3

如何解决《GCC:程序不适用于编译选项-O3》经验,为你挑选了5个好方法。

当我用优化(选项-O1,-O2,-O3等)编译它时,我正在编写一个不起作用的C++程序(我遇到了分段错误),但是当我编译它时它工作得很好优化.

我的代码中是否有错误的可能性?或者我应该假设这是GCC中的错误?

我的GCC版本是3.4.6.

这种问题有没有已知的解决方法?

我的程序的优化和未优化版本之间的速度差异很大,所以我真的需要使用优化.


这是我原来的算子.没有优化级别的工作正常,并且在任何优化级别都会引发分段错误:

struct distanceToPointSort{
    indexedDocument* point ;
    distanceToPointSort(indexedDocument* p): point(p) {}
    bool operator() (indexedDocument* p1,indexedDocument* p2){
        return distance(point,p1) < distance(point,p2) ;
    }
} ;

并且这个可以完美地适用于任何级别的优化:

struct distanceToPointSort{
    indexedDocument* point ;
    distanceToPointSort(indexedDocument* p): point(p) {}
    bool operator() (indexedDocument* p1,indexedDocument* p2){

        float d1=distance(point,p1) ;
        float d2=distance(point,p2) ;

        std::cout << "" ;  //without this line, I get a segmentation fault anyways

        return d1 < d2 ;
    }
} ;

不幸的是,这个问题难以重现,因为它发生了一些特定的值.我在对超过一千个向量中的一个进行排序时得到了分段错误,所以它实际上取决于每个向量具有的特定值组合.



1> CesarB..:

现在您发布了代码片段并找到了工作解决方法(@Windows程序员的答案),我可以说也许您正在寻找的是-ffloat-store.

-ffloat店

不要将浮点变量存储在寄存器中,并禁止可能改变浮点值是从寄存器还是内存中获取的其他选项.

这个选项可以防止诸如68000之类的机器上出现不希望的过度精度,其中浮动寄存器(68881)比双重应该具有更高的精度.同样适用于x86架构.对于大多数程序来说,多余的精度只会很好,但有些程序依赖于IEEE浮点的精确定义.在修改它们以将所有相关的中间计算存储到变量中之后,对这些程序使用-ffloat-store.

资料来源:http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Optimize-Options.html



2> Martin York..:

我会先假设你的代码错了.
虽然很难分辨.

您的代码是否编译为0警告?

 g++ -Wall -Wextra -pedantic -ansi



3> Artelius..:

这里有一些似乎有用的代码,直到你点击-O3 ...

#include 

int main()
{
    int i = 0, j = 1, k = 2;
    printf("%d %d %d\n", *(&j-1), *(&j), *(&j+1));
    return 0;
}

没有优化,我得到"2 1 0"; 有了优化,我得到了"40 1 2293680".为什么?因为我和k得到了优化!

但我正在取j的地址并走出分配给j的内存区域.标准不允许这样做.您的问题很可能是由与标准的类似偏差引起的.

我觉得valgrind在这些时候经常会有所帮助.

编辑:一些评论者认为标准允许任意指针算术.它不是.请记住,某些体系结构具有有趣的寻址方案,对齐可能很重要,如果溢出某些寄存器,则可能会出现问题!

关于向指针添加/从指针中减去一个整数的[草稿]标准的字样(强调添加):

"如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不会产生溢出; 否则,行为是未定义的. "

看到&j甚至没有指向数组对象,&j-1和&j + 1几乎不能指向同一个数组对象的一部分.因此,简单地评估&j + 1(更不用说解除引用它)是未定义的行为.

在x86上,我们可以非常自信地将一个添加到指针是相当安全的,只需将我们带到下一个内存位置即可.在上面的代码中,当我们对内存包含的内容做出假设时会出现问题,当然标准不会接近.


请将其编辑为"这是一些在低于-O3的级别意外工作的错误代码".当然你后来澄清了它,但是你的第一行误导了这次讨论的读者.
在-O3处失败的任何代码都是在-O3以下意外工作的错误代码.当然,除非真的是编译器错误.这个例子让代码特别糟糕.我认为这是故意说明这一点.

4> Adam Rosenfi..:

错误在您的代码中.根据C标准,你可能正在做一些调用未定义行为的东西,它恰好在没有优化的情况下工作,但是当GCC对执行其优化做出某些假设时,代码会在这些假设不正确时中断.确保使用该-Wall选项进行编译,这-Wextra可能也是一个好主意,看看是否有任何警告.您也可以尝试-ansi-pedantic,但这些可能会导致误报.



5> Windows prog..:

作为一个实验,试着看看这是否会迫使编译器一致地舍入所有内容.

volatile float d1=distance(point,p1) ;
volatile float d2=distance(point,p2) ;
return d1 < d2 ;

推荐阅读
郑小蒜9299_941611_G
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有