C优化算法

C优化算法,c,optimization,gcc,for-loop,C,Optimization,Gcc,For Loop,我正在编写一个包含4个嵌套for循环的算法。问题是在每一级都会更新一个指针。最里面的循环只使用一个指针。该算法计算复杂。当我包含一条记录索引组合和计数结果的调试语句时,我得到了正确的答案。省略调试语句时,计数不正确。该程序使用gcc上的-O3选项编译。为什么会发生这种情况?在责怪优化器之前,一定要让代码通过valgrind、Purify等程序。尤其是在指责与指针有关的事情时 这并不是说优化器没有坏,但很可能是你。我已经在各种C++编译器上工作,看到我的SEG错误只发生在优化代码中。通常,人们会在

我正在编写一个包含4个嵌套for循环的算法。问题是在每一级都会更新一个指针。最里面的循环只使用一个指针。该算法计算复杂。当我包含一条记录索引组合和计数结果的调试语句时,我得到了正确的答案。省略调试语句时,计数不正确。该程序使用gcc上的-O3选项编译。为什么会发生这种情况?

在责怪优化器之前,一定要让代码通过valgrind、Purify等程序。尤其是在指责与指针有关的事情时

这并不是说优化器没有坏,但很可能是你。我已经在各种C++编译器上工作,看到我的SEG错误只发生在优化代码中。通常,人们会在为字符串分配空间时忘记计算\0等。幸运的是,当程序以不同的-O设置运行时,在哪个页面上分配了您


还有一些重要的问题:你到底在处理受限指针吗?

听起来好像有什么东西在访问不应该访问的内存。调试符号以推迟坏消息而闻名

是纯C还是有什么疯狂的东西,比如内联汇编


但是,在valgrind上运行它以检查是否可能发生这种情况。另外,您是否尝试过使用不同的优化级别进行编译?没有调试和优化?

打印编译器生成的汇编代码,并进行优化。与未经优化的汇编语言代码列表进行比较

编译器可能已经计算出某些变量可以消除的原因。计算中没有使用它们。您可以尝试将WIT与编译器匹配,并排除未使用的变量

编译器可能已经用一个等式替换了一个
循环。在某些情况下(删除未使用的变量后),循环可以由一个简单的等式代替。例如,向变量添加1的循环可以用乘法语句替换

printf("%i %i\n", x, y = x - z);

您可以通过将某个变量声明为
volatile来告诉编译器将其释放。
volatile
关键字告诉编译器,变量的值可能会在程序之外被更改,编译器不应缓存或删除变量。这是嵌入式系统编程中的一种流行技术。

最有可能的是,您的程序以某种方式利用了未定义的行为,这种行为在没有优化的情况下对您有利,但在
-O3
优化的情况下,它会对您不利


我在我的一个项目中也有过类似的经历-它在
-O2
中运行良好,但在
-O3
中出现故障。我在我的代码中大量使用了
setjmp()
/
longjmp()
,我必须使一半的变量
volatile
才能工作,所以我决定
-O2
足够好。

没有代码这很困难,但我以前见过一些东西

调试print语句常常最终成为编译器知道的值的唯一用户。如果没有print语句,编译器认为它可以消除计算或存储该值所需的任何操作和内存需求

当print语句的参数列表中包含副作用时,也会发生类似的情况

printf("%i %i\n", x, y = x - z);
另一种类型的错误可能是:

for( i = 0; i < END; i++) {
     int *a = &i;
     foo(a);
}
if (bar) {
     int * a;
     baz(a);
}
(i=0;i{ int*a=&i; 傅(甲),; } 如果(巴){ int*a; baz(a); } 这段代码可能会得到预期的结果,因为编译器可能会选择将两个a变量存储在同一位置,因此第二个a将具有另一个a具有的最后一个值

内联函数可能会有一些奇怪的行为,或者您以某种方式依赖于它们没有内联(或者有时相反),这通常是未优化代码的情况

您绝对应该尝试编译时将警告调到最大值(-Wall for gcc)。 这通常会告诉您有关风险代码的信息

(编辑) 只是想到了另一个

如果引用变量的方法不止一种,那么在没有优化的情况下,可能会出现问题,但在出现优化时会出现问题。这主要有两种方式

第一个是信号处理程序或另一个线程是否可以更改值。您需要告诉编译器这一点,以便它知道任何假定值需要重新加载和/或存储的访问。这是通过使用volatile关键字完成的


第二个是别名。这是指创建两种不同的方式来访问同一内存。编译器通常会很快假设您使用的是别名指针,但并非总是如此。此外,它们是一些人的优化标志,告诉他们不要太快做出这些假设,以及你可以愚弄编译器的方式(疯狂的东西,比如
,而(foo!=bar){foo++;}*foo=x;
显然不是bar-to-foo的副本)。

有代码吗?我猜你的代码中有一个bug,优化带来了一些不同于未优化的方式。请发布代码。虽然可能是优化器错误生成了错误的代码,但也可能是实现中的错误假设导致了不确定的行为。如果看不到代码,就不可能说出是哪一个。虽然您可能在优化器中发现了一个bug,但更可能的是您的代码出了问题(例如,依赖于未初始化变量的值),并且在调试语句中加入一些更改,使其“工作”。但是,这只是猜测,没有看到实际的代码。试着把它缩小到最小的例子t