为什么gfortran不给出符号回溯?

时间:2015-02-19 17:15:53

标签: debugging gfortran backtrace

使用-g otion使用gfortran编译器运行我的fortran代码后,出现以下错误:

Program received signal SIGFPE: Floating-point exception - erroneous   arithmetic operation.

Backtrace for this error:
#0  0x7F2EE30E57D7
#1  0x7F2EE30E5DDE
#2  0x7F2EE2820D3F
#3  0x7F2EE2DEC913
#4  0x408A97 in __aerosols_MOD_moment_logn at aerosols.f90:45
#5  0x408A02 in __aerosols_MOD_set_aerosol at aerosols.f90:78 (discriminator 20)
#6  0x6D357B in __test_cases_2d_MOD_standard_2d_cases at test_cases_2d.f90:210
#7  0x67E9FC in __set_profiles_MOD_read_profiles_standard at set_profiles.f90:118
#8  0x463BF8 in __main_MOD_main_loop at main.f90:48
#9  0x401F05 in kid at KiD.f90:17
Floating point exception (core dumped)

我不明白为什么前四个回溯不能告知错误跟踪。我尝试使用addr2line来查找地址,但它也没有提供信息。我怎样才能了解错误跟踪?

3 个答案:

答案 0 :(得分:1)

  

我不明白为什么前四个回溯不能告知错误跟踪。

您获得的堆栈跟踪来自某种内部Fortran错误报告机制,而不是您的问题所暗示的GDB。该机制可能无法处理共享库(请注意,所有“缺失”帧都远离应用程序帧 - 丢失的帧可能位于共享库中。)

解决方案:在GDB下运行程序,并使用where命令。 GDB知道如何读取共享库的符号信息,并且可能会为您提供缺少的信息。

答案 1 :(得分:0)

有几种方法可以解决一些没有有用信息的堆栈帧。

一种方法是,如果您的程序有错误并破坏堆栈。在这种情况下,我建议转向valgrind以找到问题。

另一种方法是如果有问题的代码是在没有debuginfo的情况下编译的。有时您可能仍会在此处获得一些信息,但并非总是如此。在这种情况下,解决方案是使用-g重新编译代码。

第三种方法是如果你的程序包含一个即时编译器,并且执行在JITted代码中停止。鉴于你在FORTRAN工作,我怀疑这不是你的问题。

告诉代码可能来自何处的一种方法是使用info sharedinfo proc mappings,并搜索地址列表以查看来自违规帧的PC值的位置。 (是的,手动执行此操作很不幸。)如果PC符合列出的某个地图,那么您就知道在哪里修复-g问题。如果它不适合任何地方,那么堆栈很可能会被破坏。

答案 2 :(得分:0)

gfortran打印的符号回溯不是由gdb完成的,而是由addr2line完成的。问题是addr2line检查磁盘上的二进制文件而不是内存中的程序映像。因此,对于以某种随机偏移量加载到内存中的共享库(出于安全原因),addr2line无法将地址转换为符号名称,因此gfortran回溯机制会回退到打印地址。

您可以通过静态编译来解决这个问题,允许addr2line转换libgfortran(gfortran运行时库)中的地址。通常,前几个堆栈帧来自libgfortran回溯打印功能,无论如何。