如何解决Gfortran中循环依赖对象链接的未定义引用问题
Gfortran循环依赖子程序的链接问题解决办法
问题背景
你遇到的是Fortran子程序循环依赖导致的Gfortran链接错误:两个文件互相交叉调用对方的子程序(文件1含TEST1/TEST2,均调用TEST3;文件2含TEST3/TEST4,分别调用TEST2/TEST1),无论链接顺序如何都报未定义引用,但Silverfrost ftn95不受影响。
可行解决办法
1. 手动添加EXTERNAL声明(你的提问方案)
这个方法确实能解决问题:在每个调用其他子程序的代码开头,用EXTERNAL声明被调用的子程序,比如:
- 在TEST1里加
EXTERNAL TEST3 - 在TEST2里加
EXTERNAL TEST3 - 在TEST3里加
EXTERNAL TEST2 - 在TEST4里加
EXTERNAL TEST1
它会告诉编译器“这个子程序在其他位置定义”,编译时生成正确的符号引用,链接阶段就能解析交叉依赖的符号,无需在意链接顺序。
2. 使用模块(Module)统一声明接口
这是最规范的长期解决方案:
- 新建模块文件(如
subs_mod.f90),在其中声明所有子程序的接口:module subs_mod implicit none interface subroutine test1() end subroutine test1 subroutine test2() end subroutine test2 subroutine test3() end subroutine test3 subroutine test4() end subroutine test4 end interface end module subs_mod - 所有包含子程序的文件开头添加
use subs_mod,编译阶段就能识别所有子程序接口,从根源避免链接符号问题。
3. 使用Gfortran链接器扫描选项
无需修改代码,通过链接器参数让其多次扫描目标文件解析循环依赖:
gfortran -o program -Wl,--start-group file1.o file2.o -Wl,--end-group
--start-group和--end-group会让链接器对组内文件重复扫描,直到所有符号都被解析。
为什么Silverfrost ftn95不受影响?
ftn95的链接器默认支持循环依赖的符号解析,或是其编译模式在编译阶段就已收集全量符号信息,不需要依赖链接顺序;而Gfortran使用的GNU ld链接器默认单次扫描目标文件,遇到未定义符号不会回溯查找,因此循环依赖会触发报错。
内容的提问来源于stack exchange,提问作者Stam
相关产品推荐
相关产品推荐

