我从内存分配语句中得到了分段错误,因为我已将一些不相关的过程链接到二进制文件。
我有一个非常简单的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没有给我任何期望内存地址的提示。
实际上未调用的链接例程如何使程序崩溃?
答案 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
结果是一样的。