在开发一个大型Fortran软件时,我经常遇到这个错误,特别是在使用-O2编译以获得更好的性能时。
在某些情况下,错误是真实的,可以纠正,但在其他情况下,我没有发现任何错误,并假设它是由-O2在代码周围移动引起的。由于我的老式调试技术是在错误发生的地方附近添加write语句,我发现当我这样做时,错误通常会消失。
也许是因为-O2优化在处理这类语句时比较小心。
最近,我在一个循环中遇到了这个错误,这个循环并不复杂,时间也不重要,在循环中添加一个write语句可以防止这个错误。当我删除write语句时,错误又出现了。为了避免在运行程序时产生大量无意义的输出,我发现写入一个内部字符就足够了,这样对用户来说什么都不会改变。
在没有-O2的情况下编译代码时没有错误,但是循环在使用许多局部变量的模块中,我不知道如何在没有-O2的情况下单独编译模块中的子例程。
我在Linux和Windows上使用GNU Fortran 7.2.0(最近的错误只发生在Linux上,但以前我在Windows上也遇到过类似的问题)。我没有访问任何其他编译器的权限,但我的代码是免费的,并且已经用其他编译器编译过,没有报告任何问题。
因此,我的问题是,是否可以对模块内的一小部分代码关闭-O2,或者是否有比添加write语句更好的替代方法来防止-O2在特定子例程内的代码中移动。
1条答案
按热度按时间xam8gpfp1#
我是通过网络搜索来到这里的,为了帮助大家,我想分享一下我的解决方案。许多评论者提到了未初始化变量的可能性。我的代码中没有这样的警告,但我在子例程中分配存储空间时产生了明显相同的效果,因为编译器可能没有意识到新分配的内存将在下一行中使用。
我在模块中意外地包含了一个可分配数组,然后将其作为参数传递给第一个执行分配的子例程(使用模块中的名称),然后立即开始使用我作为参数传入的名称为数组元素赋值。当我从-O 1移到-O2时,它停止工作。而不是检测问题,-fcheck=bounds实际上导致代码在没有segfault的情况下运行。
我通过使用-O2 -g -traceback而不检查边界来定位出错行,当我开始一致地使用作为参数传递的名称来引用数组时,问题就消失了。