Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么是未定义的引用/未解决的外部符号错误?如何在Fortran中修复它?_Fortran_Linker Errors_Undefined Reference_Unresolved External - Fatal编程技术网

什么是未定义的引用/未解决的外部符号错误?如何在Fortran中修复它?

什么是未定义的引用/未解决的外部符号错误?如何在Fortran中修复它?,fortran,linker-errors,undefined-reference,unresolved-external,Fortran,Linker Errors,Undefined Reference,Unresolved External,我正在尝试构建一个Fortran程序,但是我得到了关于未定义引用或未解析外部符号的错误。我已经看过这些错误,但是答案大多是针对C++的。 使用Fortran编写时,这些错误的常见原因是什么?如何修复/防止它们?不链接库 未定义引用/未解析外部符号错误最常见的原因是未能链接提供符号的库(通常是函数或子例程) 例如,当使用BLAS库中的子例程(如DGEMM)时,必须在链接步骤中使用提供该子例程的库 在最简单的用例中,链接与编译相结合: gfortran my_source.f90 -lblas -

我正在尝试构建一个Fortran程序,但是我得到了关于未定义引用或未解析外部符号的错误。我已经看过这些错误,但是答案大多是针对C++的。 使用Fortran编写时,这些错误的常见原因是什么?如何修复/防止它们?

不链接库
未定义引用
/
未解析外部符号
错误最常见的原因是未能链接提供符号的库(通常是函数或子例程)

例如,当使用BLAS库中的子例程(如
DGEMM
)时,必须在链接步骤中使用提供该子例程的库

在最简单的用例中,链接与编译相结合:

gfortran my_source.f90 -lblas
-lblas
告诉链接器(这里由编译器调用)链接
libblas
库。它可以是动态库(.so、.dll)或静态库(.a、.lib)。 请注意,库的名称可以不同,因为BLAS有多个实现(MKL、OpenBLAS、GotoBLAS等)。 但是它总是从
lib…
缩短为
l…
,就像
liopenblas.so
-lopenblas
一样

当链接和编译分离时,在链接步骤中链接库:

gfortran -c my_source.f90 -o my_source.o
gfortran my_source.o -lblas

类似于这些消息的链接时间错误的原因可能与链接器的更一般用途的原因相同,而不仅仅是编译了Fortran程序。其中有些内容涉及到C++链接,这里没有指定库,或者提供错误的顺序。

然而,在编写Fortran程序时,有一些常见的错误会导致链接错误

不支持的本质 如果子例程引用旨在引用内在子例程,那么如果编译器未提供该子例程内在,则可能导致链接时间错误:它被视为外部子例程

  implicit none
  call unsupported_intrinsic
end
如果编译器未提供
不受支持的\u intrinsive
,我们可能会看到如下链接错误消息

undefined reference to `unsupported_intrinsic_'
undefined reference to `main'
如果我们使用的是非标准的,或者不是通常实现的,我们可以通过以下两种方式帮助我们的编译器报告这一点:

  implicit none
  intrinsic :: my_intrinsic
  call my_intrinsic
end program
如果
my_intrinsic
不是受支持的内部版本,则编译器将发出一条有用的消息:

Error: ‘my_intrinsic’ declared INTRINSIC at (1) does not exist
内在函数没有这个问题,因为我们使用的是
隐式none

  implicit none
  print *, my_intrinsic()
end
对于某些编译器,我们可以使用Fortran 2018
隐式
语句对子例程执行相同的操作

  implicit none (external)
  call my_intrinsic
end
外部程序而不是模块程序 正如我们可以尝试在程序中使用模块过程,但忘记将定义该过程的对象提供给链接器一样,我们也可以意外地告诉编译器使用外部过程(具有不同的链接符号名称)而不是模块过程:

module mod
  implicit none
contains
  integer function sub()
    sub = 1
  end function
end module

  use mod, only :
  implicit none

  integer :: sub

  print *, sub()

end
或者我们可能会忘记使用模块。同样,当我们错误地引用外部程序而不是外部程序时,我们经常看到这一点

当我们忘记使用模块时,使用
implicit none(external)
可以帮助我们,但这不会捕获我们显式声明函数为外部函数的情况。我们必须小心,但是如果我们看到像这样的链接错误

undefined reference to `sub_'
然后我们应该认为我们引用了一个外部过程
sub
,而不是一个模块过程:“模块名称空间”没有任何名称混乱。这是一个强烈的暗示,我们应该在哪里寻找

错误指定的绑定标签 如果我们与C进行互操作,那么很容易错误地指定符号的链接名称。如果不使用标准的互操作性工具,这是非常容易的,所以我不会费心指出这一点。如果您看到与C函数相关的链接错误,请仔细检查

如果使用标准设备,仍有可能出现故障。区分大小写是一种方式:链接符号名称区分大小写,但如果不全是小写,则必须告知Fortran编译器大小写:

   interface
     function F() bind(c)
       use, intrinsic :: iso_c_binding, only : c_int
       integer(c_int) :: f
     end function f
  end interface

  print *, F()
end
告诉Fortran编译器向链接器询问符号
f
,尽管我们在这里称它为
f
。如果符号真的被称为
F
,我们需要明确地说:

   interface
     function F() bind(c, name='F')
       use, intrinsic :: iso_c_binding, only : c_int
       integer(c_int) :: f
     end function f
  end interface

  print *, F()
end
如果您看到链接错误因情况而异,请检查绑定标签

对于具有绑定标签的数据对象也是如此,并且还要确保任何具有链接关联的数据对象在任何C定义和链接对象中都有匹配的名称

不提供主程序 除非另有说明,否则编译器通常会假定它正在编译一个主程序,以便(使用链接器)生成一个可执行文件。如果我们不编译主程序,那就不是我们想要的。也就是说,如果我们正在编译模块或外部程序,以便以后使用:

module mod
  implicit none
contains
  integer function f()
    f = 1
  end function f
end module

subroutine s()
end subroutine s
我们可能会收到这样的消息

undefined reference to `unsupported_intrinsic_'
undefined reference to `main'
这意味着我们需要告诉编译器我们没有提供Fortran主程序。这通常使用
-c
标志,但如果尝试构建库对象,则会有不同的选项。在这种情况下,编译器文档将提供适当的选项。

编译器自己的库存在问题 大多数Fortran编译器需要将代码与它们自己的库相链接。这应该会自动发生,而无需您进行干预,但这可能会由于一些原因而失败

如果使用
gfortran
进行编译,此问题将显示为对
libgfortran
中符号的未定义引用,这些符号都命名为
\u gfortran…
。这些错误消息如下所示

对“\u gfortran\u…”的未定义引用

此问题的解决方案取决于其原因:

  • 未安装编译器库
  • 编译器库应该已自动安装
    gcc -o program fortran_object.o c_object.o -lgfortran
    
    gfortran -c module.f90
    gfortran program.f90 -o program
    
    gfortran -c module.f90
    gfortran module.o program.f90 -o program
    
    gfortran -c module.f90
    gfortran -c program.f90
    gfortran module.o program.o -o program