【问题标题】:Writing to screen solves segmentation error?写入屏幕可以解决分段错误?
【发布时间】:2014-08-28 06:24:08
【问题描述】:

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

 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

像这样运行代码,在屏幕上产生以下打印:

退出对象 0.0000000000000000 9997.5723796583643

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

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

程序收到信号 SIGSEGV:分段错误 - 无效内存 参考。

此错误的回溯:
#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。编译器不显示任何警告。

在尝试了一周的各种事情并扫描了一半的互联网以寻找正在发生的事情的线索之后,我想我应该在 Objee 中打印 V 的形状,看看 fortran 给了我什么 - 不知何故,结果它解决了问题:

subroutine Objee(ap,V)

 ...

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

end subroutine Objee

在屏幕上产生以下内容:

 Exit Objee   0.0000000000000000        9997.5723796583643     
 After Objee   0.0000000000000000        9997.5723796583643

魔法!一切正常,似乎一切正常。有人可以向我解释这里发生了什么吗?此外,我如何解决发生的任何事情,而无需在每次调用 Objee 时在屏幕上打印 shape(V)(这将是数千个......)

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

==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 行(输出指向的)是:

64          call Objee(apmax,Val)

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

作为一个没有经验的用户,我真的不明白这对我有什么帮助,除了指出我已经怀疑导致崩溃的代码部分。我在这里错过了什么?

【问题讨论】:

  • ObjeeModule 里面吗?您是否尝试过编译所有编译器警告?您能否在您的问题中添加apV 的完整定义(以及nag_wp 的定义)?
  • 谢谢,彼得!我已经在上面添加了您要求的信息:对您的前两个问题都是肯定的; ap 和 V 是实数(kind=nag_wp),就像 apmax 和 Val 一样; nag_wp 是我从 NAG 库调用过程时需要使用的数据类型。
  • 您在使用 OpenMP 吗?如果您删除选项-fopenmp,问题会消失吗?
  • 我刚刚尝试在没有 OpenMP 的情况下运行它,但问题仍然存在。
  • 你使用debugger吗?似乎回溯更像是没有调试符号。你在linux上吗?在这种情况下使用valgrind

标签: segmentation-fault fortran


【解决方案1】:

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

添加诸如输出之类的“随机”语句可以阻止内存错误的原因是,非法内存访问可能会对新代码造成可以容忍的破坏,而在它造成致命破坏之前,例如过度写入地址使用数据值,创建非法地址。这些错误可能难以诊断,因为致命错误似乎与代码错误无关。第一段中描述的工具可以提供很大帮助。

【讨论】:

  • 感谢您的回答!我已经编辑了这个问题来解决你的观点。 ap 和 V 是真实的(kind=nag_wp),像 apmax 和 Val 一样排名 0,所以我认为 1)或 2)都不适用。我也在使用 gfortran 提供的所有警告,但编译器似乎没有找到任何要显示的错误或警告。最后,我在 FindVee 中使用的模块的接口块中包含了 Objee,但问题仍然存在。
猜你喜欢
  • 2019-06-12
  • 2021-06-26
  • 1970-01-01
  • 1970-01-01
  • 2021-06-06
  • 1970-01-01
  • 2020-03-29
  • 2012-11-30
  • 1970-01-01
相关资源
最近更新 更多