如何在运行时发生段错误只是因为链接未使用的模块?

时间:2015-05-17 14:26:38

标签: gcc fortran gfortran

我从内存分配语句中得到了分段错误,因为我已将一些不相关的过程链接到二进制文件。

我有一个非常简单的Fortran程序:

program whatsoever
!USE payload_modules

double precision,allocatable:: Vmat(:,:,:)

allocate(Vmat(2,2,2))
Vmat=1
write(*,*) Vmat
deallocate (Vmat)
! some more lines of code using procedures from payload_module
end program whatsoever

使用gfortran whatsoever.f95 -o whatsoever进行编译会导致具有预期行为的程序。当然,此程序不会打印八次1.000,而是打电话给payload_modules,但隐藏在评论中。但是,如果我使用发布的模块编译和链接程序

gfortran -c -g -fPIC -ffpe-trap=overflow -pedantic -fbounds-check \
    -fimplicit-none payload_module1.f90 payload_module2.f90 whatsever.f95

gcc -g -nostdlib -v -Wl,--verbose  -std=gnu99 -shared -Wl,-Bsymbolic-functions \
    -Wl,-z,relro -o whatsoever whatsoever.o payload_module1.o payload_module2.o

程序whatsoever不再运行。我在allocate语句中遇到了段错误。我还没有取消注释与模块相关的行(但是,取消注释它们会导致相同的行为)!

我知道有效载荷模块的代码没有错误,因为我之前从R运行它并将此工作代码包装到f90模块中。没有名称冲突;模块中没有任何内容称为Vmat。模块中只有一个对allocate的调用。它从来没有造成任何麻烦。还剩下大量的记忆。 gdb没有给我任何期望内存地址的提示。

实际上未调用的链接例程如何使程序崩溃?

1 个答案:

答案 0 :(得分:4)

使用

编译代码
gfortran whatsoever.f95 -o whatsoever

正在运行,因为您链接到系统库,一切都已就绪。这将对应于

gfortran whatsoever.f95 payload_module1.f90 payload_module2.f90 -o whatsoever

哪个也行。您使用的命令省略了系统库,并且代码在您第一次从那里调用函数时失败(分配)。您没有看到缺少库,因为您创建了一个共享对象(通常在以后链接到库)。

您选择单独编译对象并将它们链接到可执行文件中。使用gcc为Fortran程序执行此操作需要指定Fortran库,因此缺少-lgfortran

我不确定编译选项的特定选择... -shared通常用于库,你确定你想要一个共享二进制文件(无论是什么)? 使用-nostdlib,您告诉编译器不要链接到系统库。然后,您需要指定这些库(您不需要)。

对于主程序test.F90和模块payload.F90,我运行

gfortran -c -g -fPIC -ffpe-trap=overflow -pedantic -fbounds-check \
   -fimplicit-none payload.F90 test.F90

gcc -g -v -Wl,--verbose  -std=gnu99 -Wl,-Bsymbolic-functions \
   -Wl,-z,relro -lgfortran -o whatsoever test.o payload.o

这正确编译并执行。

使用gfortran的高级选项可能更容易:

gfortran -g -fPIC -ffpe-trap=overflow -pedantic -fbounds-check \
  -fimplicit-none -Wl,-Bsymbolic-functions -Wl,-z,relro \
  payload.F90 test.F90 -o whatsoever

结果是一样的。