写入屏幕可解决细分错误? [英] Writing to screen solves segmentation error?

查看:66
本文介绍了写入屏幕可解决细分错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从另一个子例程(FindVee)中调用(外部)子例程Objee:

I'm calling (external) subroutine Objee from within another subroutine (FindVee):

 subroutine FindVee(EVone,Vw0,Ve,Fye)

  use nag_library, only: nag_wp

  use My_interface_blocks, only: Objee

  ...

  implicit none

  real(kind=nag_wp) :: apmax, Val

  ...

  call Objee(apmax,Val)

  write(*,*) 'After Objee', apmax, Val

  ...

 end subroutine FindVee

子例程对象是:

subroutine Objee(ap,V)

 use nag_library, only: nag_wp

 ...

 implicit none

  real(kind=nag_wp), intent(in) :: ap

  real(kind=nag_wp), intent(out):: V

 ...

 V = U(x,sigma) + beta*piy*yhat1(Nav*(Nav+1)/2) + &
   & beta*eta*(1.0e0-piy)*yhat2(Nav*(Nav+1)/2)

 V = - V

 write(*,*) 'Exit Objee', ap, V

end subroutine Objee

运行这样的代码,在屏幕上显示以下内容:

Running the code like this, produces the following print on screen:

退出对象0.0000000000000000 9997.5723796583643

Exit Objee 0.0000000000000000 9997.5723796583643

程序接收到的信号SIGBUS:访问程序的未定义部分内存对象.

Program received signal SIGBUS: Access to an undefined portion of a memory object.

此错误的回溯记录:
#0 0x7FAA7ADFF7D7
#1 0x7FAA7ADFFDDE
#2 0x7FAA7A533FEF
#3 0x423B29 in findvee_

Backtrace for this error:
#0 0x7FAA7ADFF7D7
#1 0x7FAA7ADFFDDE
#2 0x7FAA7A533FEF
#3 0x423B29 in findvee_

程序接收到的信号SIGSEGV:分段错误-无效的存储器参考.

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

此错误的回溯记录:
#0 0x7FAA7ADFF7D7
#1 0x7FAA7ADFFDDE
#2 0x7FAA7A533FEF
#3 0x7FAA7A0B9BA0
#4 0x7FAA7A0BAEFD
#5 0x7FAA7ADFF7D7
#6 0x7FAA7ADFFDDE
#7 0x7FAA7A533FEF
#8 0x423B29 in findvee_分段错误(核心已转储)

Backtrace for this error:
#0 0x7FAA7ADFF7D7
#1 0x7FAA7ADFFDDE
#2 0x7FAA7A533FEF
#3 0x7FAA7A0B9BA0
#4 0x7FAA7A0BAEFD
#5 0x7FAA7ADFF7D7
#6 0x7FAA7ADFFDDE
#7 0x7FAA7A533FEF
#8 0x423B29 in findvee_ Segmentation fault (core dumped)

我正在使用gfortran 4.8.1,使用以下选项:-fopenmp -fcheck = all -fcheck = bounds -Wall -Wimplicit-interface -Wimplicit-procedure.编译器不显示任何警告.

I'm using gfortran 4.8.1, using the following options: -fopenmp -fcheck=all -fcheck=bounds -Wall -Wimplicit-interface -Wimplicit-procedure. The compiler doesn't show any warnings.

经过一周的尝试,尝试了各种各样的事情,并扫描了一半的互联网以了解发生了什么事情,我想我会在Objee中打印出V形,然后看看fortran给我带来了什么—事实证明它可以解决问题:

After a week of trying all sorts of things and scanning half the internet for a clue of what was happening, I thought I'd print the shape of V in Objee and see what fortran gave me- somehow it turns out it solves the problem:

subroutine Objee(ap,V)

 ...

 write(*,*) 'Exit Objee', ap, V, shape(V)

end subroutine Objee

在屏幕上显示以下内容:

produces the following on screen:

 Exit Objee   0.0000000000000000        9997.5723796583643     
 After Objee   0.0000000000000000        9997.5723796583643

魔术!一切正常,似乎一切正确.有人可以告诉我这是怎么回事吗?而且,在每次调用Objee时(在成千上万个...中),如何在不在屏幕上打印shape(V)的情况下解决所有问题?

Magic! Everything works and it seems like everything's right. Could somebody explain to me what's going on here? And also, how I can solve whatever was going on without printing shape(V) on screen with every call to Objee (which will be in the thousands...)

运行 valgrind ./programa --leak-check = full 后,我得到以下输出:

After running valgrind ./programa --leak-check=full, I obtain the following output:

==2784== Invalid write of size 8
==2784==    at 0x423B3F: findvee_ (FindVee.f95:66)
==2784==    by 0x8: ???
==2784==  Address 0x7ffffffffffffda8 is not stack'd, malloc'd or (recently) free'd
==2784== 

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0x4E4D7D7
#1  0x4E4DDDE
#2  0x56A3FEF
#3  0x423B3F in findvee_ at FindVee.f95:66
==2784== Invalid read of size 8
==2784==    at 0x5C7FBA0: ??? (in /lib/x86_64-linux-gnu/libgcc_s.so.1)
==2784==    by 0x5C80EFD: _Unwind_Backtrace (in /lib/x86_64-linux-gnu/libgcc_s.so.1)
==2784==    by 0x4E4D7D7: _gfortran_backtrace (in /usr/lib/x86_64-linux-gnu/libgfortran.so.3.0.0)
==2784==    by 0x4E4DDDE: ??? (in /usr/lib/x86_64-linux-gnu/libgfortran.so.3.0.0)
==2784==    by 0x56A3FEF: ??? (in /lib/x86_64-linux-gnu/libc-2.17.so)
==2784==    by 0x423B3E: findvee_ (FindVee.f95:64)
==2784==    by 0x8: ???
==2784==  Address 0x8000000000000008 is not stack'd, malloc'd or (recently) free'd
==2784== 
==2784== 
==2784== Process terminating with default action of signal 11 (SIGSEGV)
==2784==  General Protection Fault
==2784==    at 0x5C7FBA0: ??? (in /lib/x86_64-linux-gnu/libgcc_s.so.1)
==2784==    by 0x5C80EFD: _Unwind_Backtrace (in /lib/x86_64-linux-gnu/libgcc_s.so.1)
==2784==    by 0x4E4D7D7: _gfortran_backtrace (in /usr/lib/x86_64-linux-gnu/libgfortran.so.3.0.0)
==2784==    by 0x4E4DDDE: ??? (in /usr/lib/x86_64-linux-gnu/libgfortran.so.3.0.0)
==2784==    by 0x56A3FEF: ??? (in /lib/x86_64-linux-gnu/libc-2.17.so)
==2784==    by 0x423B3E: findvee_ (FindVee.f95:64)
==2784==    by 0x8: ???
==2784== 
==2784== HEAP SUMMARY:
==2784==     in use at exit: 3,859 bytes in 20 blocks
==2784==   total heap usage: 157 allocs, 137 frees, 300,126 bytes allocated
==2784== 
==2784== LEAK SUMMARY:
==2784==    definitely lost: 58 bytes in 1 blocks
==2784==    indirectly lost: 0 bytes in 0 blocks
==2784==      possibly lost: 0 bytes in 0 blocks
==2784==    still reachable: 3,801 bytes in 19 blocks
==2784==         suppressed: 0 bytes in 0 blocks
==2784== Rerun with --leak-check=full to see details of leaked memory
==2784== 
==2784== For counts of detected and suppressed errors, rerun with: -v
==2784== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)
Segmentation fault (core dumped)

第64行和第66行(输出点指向):

Lines 64 and 66 (to which the output points) are:

64          call Objee(apmax,Val)

66          write(*,*) 'After Objee', apmax, Val

作为一个没有经验的用户,除了指向我已经怀疑会导致崩溃的代码部分之外,我真的不明白这对我有什么帮助.我在这里想念什么?

As an inexperienced user, I don't really understand how this helps me in any way, other than pointing to the portion of my code I already suspected was causing the crash. What am I missing here?

推荐答案

Fortran中的此类内存错误有两个常见原因.1)非法下标访问.2)过程调用中的实际参数与子例程的伪参数之间不匹配.现代编译器和Fortran> = 90为程序员提供了帮助,以帮助他们发现这些问题.正如Peter所建议的那样,您是否正在使用编译器(尤其是编译器)的完整警告和错误选项.运行时下标检查?(您使用的是什么编译器?)如果将过程放在模块中并 use ,则该模块Fortran将检查调用参数和子例程之间的一致性.当某个过程位于模块中时,其他过程或使用该模块的主程序将知道"其接口,从而启用此检查.通过这两种方法,将发现许多导致内存问题的错误.

Memory errors like this in Fortran have two common causes. 1) illegal subscript access. 2) Mismatch between actual arguments in a procedure call and the dummy arguments of the subroutine. Modern compilers and Fortran >=90 give the programmer help in finding these problems. As suggested by Peter, are you using the full warning and error options of your compiler, esp. run-time subscript checking? (What compiler are you using?) If you place your procedures in a module and use that module Fortran will check for consistency between the arguments of the call and the subroutine. When a procedure is in a module, its interface is "known" to other procedures or the main program that uses that module, enabling this checking. With the These two methods will find many errors that cause memory problems.

添加诸如输出之类的随机"语句可以停止内存错误的原因是,非法的内存访问可能会对可以容忍的新代码造成破坏,而在其进行致命破坏之前,例如,覆盖地址与数据值一起创建非法地址.这些错误可能很难诊断,因为致命错误似乎与代码错误无关.第一段中描述的工具可以提供很大的帮助.

The reason that adding "random" statements such as output can stop memory errors is that an illegal memory access may do damage to the new code that can be tolerated, whereas before it was doing fatal damaged, such as over writing an address with a data value, creating an illegal address. These bugs can be difficult to diagnose because the fatal error seems disconnected from the code mistake. The tools described in the first paragraph can be a big help.

这篇关于写入屏幕可解决细分错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆