Fortran调用CGNS库存在对应符号却报未定义引用错误
GCC 13下CGNS库部分符号未定义引用问题
问题背景
将Fortran模块单独编译后链接CGNS库时,部分符号(如cg_nbases_f)明明存在于库中却抛出未定义引用错误。该代码在GCC 4~8版本可正常编译链接,但在GCC 13(搭配MPICH的mpif90编译器)环境下失败。
环境配置
- Fedora 39
- GCC 13:通过
dnf install gcc gfortran安装 - MPICH 4.1:通过
dnf install mpich-devel安装 - CGNS 4.4:通过
dnf install cgnslib-mpich-devel安装 - HDF5 1.12.1:通过
dnf install hdf5-mpich-devel安装(不确定是否关联)
符号检查
执行以下命令确认cg_nbases_f存在于CGNS库中:
objdump -T $MPI_LIB/libcgns.so | grep cg_nbases_t
输出结果:
00000000000a44b0 g DF .text 0000000000000055 Base cg_nbases_f
测试代码
cgnsreading.f90(模块文件)
module cgnsreading implicit none private public talk_to_cgns contains subroutine error_check() print *, 'hi I am the bane of arthropods' end subroutine error_check subroutine talk_To_cgns() character(100) :: errmsg integer :: i = 1 integer :: nbases = 1 integer :: ierr call cg_get_error_f(errmsg) print *, errmsg ! 应输出无错误信息 call error_check() ! 应输出指定内容 call cg_nbases_f(i,nbases,ierr) ! 此处抛出未定义引用错误 end subroutine talk_To_cgns end module cgnsreading
cgnsread.f90(主程序文件)
program cgnsread use cgnsreading implicit none call talk_to_cgns() end program cgnsread
编译命令与错误信息
执行以下编译链接步骤:
mpif90 cgnsreading.f90 -c mpif90 cgnsread.f90 -c mpif90 cgnsreading.o cgnsread.o -lcgns -o cgnsread
出现错误:
/usr/bin/ld: cgnsreading.o: in function `__cgnsreading_MOD_talk_to_cgns': cgnsreading.f90:(.text+0x95): undefined reference to `cg_nbases_f_' collect2: error: ld returned 1 exit status
问题原因
- 符号命名不匹配:链接器寻找的是带后缀下划线的符号
cg_nbases_f_,但CGNS库中实际存在的是无下划线的cg_nbases_f。 - 缺少CGNS接口声明:代码中未引入CGNS的Fortran接口(如
use cgns或include 'cgnslib_f.h'),导致GCC 13的Fortran编译器对外部子程序的符号修饰规则与库中实际符号不匹配。旧版GCC(4~8)的隐式声明规则恰好能匹配库中符号,但新版GCC启用了更严格的符号修饰逻辑,导致不匹配。 - 部分符号巧合匹配:
cg_get_error_f能正常链接,大概率是因为库中同时存在带下划线和不带下划线的该符号,或者旧版隐式声明规则恰好适配,属于巧合。
解决方案
1. 引入CGNS的Fortran接口
修改cgnsreading.f90模块,添加CGNS接口声明:
module cgnsreading implicit none private public talk_to_cgns ! 引入CGNS Fortran模块,让编译器知晓正确的符号规则与参数类型 use cgns contains ! 原有代码不变 subroutine error_check() print *, 'hi I am the bane of arthropods' end subroutine error_check subroutine talk_To_cgns() character(100) :: errmsg integer :: i = 1 integer :: nbases = 1 integer :: ierr call cg_get_error_f(errmsg) print *, errmsg call error_check() call cg_nbases_f(i,nbases,ierr) end subroutine talk_To_cgns end module cgnsreading
如果use cgns无效,可替换为包含CGNS的Fortran头文件:
! 在模块开头添加 include 'cgnslib_f.h'
此时编译时需通过-I参数指定CGNS头文件路径(若系统未自动配置):
mpif90 -I$MPI_INCLUDE cgnsreading.f90 -c
2. 确认链接参数正确性
确保编译时链接的是对应MPICH版本的CGNS库,可通过mpif90 -show查看默认链接参数,确认库路径与库名是否正确。
内容的提问来源于stack exchange,提问作者Mohammed Sayyari
相关产品推荐
相关产品推荐

