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

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

问题描述

我正在从另一个子例程 (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_ Segmentation fault (core dumped)

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 可以帮助程序员找到这些问题.正如彼得所建议的那样,您是否使用编译器的完整警告和错误选项,尤其是.运行时下标检查?(您使用的是什么编译器?)如果您将您的过程放在一个模块中并使用该模块,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天全站免登陆