Fortran 中数组负索引的调试错误

发布于 2024-12-29 16:55:57 字数 314 浏览 4 评论 0原文

我这里有一个测试程序:

  program test  
  implicit none  

  integer(4) :: indp  
  integer(4) :: t1(80)  

  indp = -3  
  t1(indp) = 1  
  write(*,*) t1(indp)  

  end program test

第8行是错误的,因为indp是负数。但是当我使用“ifort”或“gfortran”编译它时,它们都找不到这个错误。 即使使用valgrind调试这个程序也找不到这个错误。 你有什么想法找到这种问题吗?

I have a test program here:

  program test  
  implicit none  

  integer(4) :: indp  
  integer(4) :: t1(80)  

  indp = -3  
  t1(indp) = 1  
  write(*,*) t1(indp)  

  end program test

in line 8 it is wrong, because the indp is negative number. but when I compile it use 'ifort' or 'gfortran' both of them cannot find this error.
and even use valgrind to debug this program it also cannot find this error.
do you have any idea find this kind of problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

沒落の蓅哖 2025-01-05 16:55:57

Fortran 编译器不需要向您发出此类警告;一般来说,如果您将 Fortran 数组的下限设置为等于或小于 -3,则 t1(-3) = 1 可能是一个完全合理的语句,例如

integer(kind=4), dimension(-5:74) :: t1(80)

肯定允许设置和读取 t1(-3)。

如果你想确保在运行时检查这些类型的错误,你可以使用 gfortran:

$ gfortran -o foo foo.f90 -fcheck=bounds
$ ./foo 
At line 8 of file foo.f90
Fortran runtime error: Array reference out of bounds for array 't1', lower bound of dimension 1 exceeded (-3 < 1)

或 ifort 中的 -fbounds-check 进行编译:

ifort -o foo foo.f90 -check bounds

$ ifort -o foo foo.f90 -check bounds
$ ./foo
forrtl: severe (408): fort: (3): Subscript #1 of the array T1 has value -3 which is less than the lower bound of 1

Image              PC                Routine            Line        Source             
foo                000000000046A8DA  Unknown               Unknown  Unknown

原因 valgrind没有意识到这一点有点微妙,但请注意,如果分配了数组,就会出现这种情况:

  program test  
  implicit none  

  integer(kind=4) :: indp  
  integer(kind=4), allocatable :: t1(:)  

  indp = -3  
  allocate(t1(80))
  t1(indp) = 1  
  write(*,*) t1(indp)  
  deallocate(t1)

  end program test

$ gfortran -o foo foo.f90 -g
$ valgrind ./foo
==18904== Memcheck, a memory error detector
==18904== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==18904== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==18904== Command: ./foo
==18904== 
==18904== Invalid write of size 4
==18904==    at 0x400931: MAIN__ (foo.f90:9)
==18904==    by 0x400A52: main (foo.f90:13)
==18904==  Address 0x5bb3420 is 16 bytes before a block of size 320 alloc'd
==18904==    at 0x4C264B2: malloc (vg_replace_malloc.c:236)
==18904==    by 0x400904: MAIN__ (foo.f90:8)
==18904==    by 0x400A52: main (foo.f90:13)
==18904== 
==18904== Invalid read of size 4
==18904==    at 0x4F07368: extract_int (write.c:450)
==18904==    by 0x4F08171: write_integer (write.c:1260)
==18904==    by 0x4F0BBAE: _gfortrani_list_formatted_write (write.c:1553)
==18904==    by 0x40099F: MAIN__ (foo.f90:10)
==18904==    by 0x400A52: main (foo.f90:13)
==18904==  Address 0x5bb3420 is 16 bytes before a block of size 320 alloc'd
==18904==    at 0x4C264B2: malloc (vg_replace_malloc.c:236)
==18904==    by 0x400904: MAIN__ (foo.f90:8)
==18904==    by 0x400A52: main (foo.f90:13)

Fortran compilers aren't required to give you warnings about things like this; and in general, t1(-3) = 1 could be a perfectly reasonable statement if you set the lower bound of your fortran array to something equal to or less than -3, eg

integer(kind=4), dimension(-5:74) :: t1(80)

would certainly allow setting and reading t1(-3).

If you want to make sure these sorts of errors are checked at runtime, you can compile with -fbounds-check with gfortran:

$ gfortran -o foo foo.f90 -fcheck=bounds
$ ./foo 
At line 8 of file foo.f90
Fortran runtime error: Array reference out of bounds for array 't1', lower bound of dimension 1 exceeded (-3 < 1)

or -check bounds in ifort:

ifort -o foo foo.f90 -check bounds

$ ifort -o foo foo.f90 -check bounds
$ ./foo
forrtl: severe (408): fort: (3): Subscript #1 of the array T1 has value -3 which is less than the lower bound of 1

Image              PC                Routine            Line        Source             
foo                000000000046A8DA  Unknown               Unknown  Unknown

The reason valgrind doesn't catch this is a little subtle, but note that it would if the array were allocated:

  program test  
  implicit none  

  integer(kind=4) :: indp  
  integer(kind=4), allocatable :: t1(:)  

  indp = -3  
  allocate(t1(80))
  t1(indp) = 1  
  write(*,*) t1(indp)  
  deallocate(t1)

  end program test

$ gfortran -o foo foo.f90 -g
$ valgrind ./foo
==18904== Memcheck, a memory error detector
==18904== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==18904== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==18904== Command: ./foo
==18904== 
==18904== Invalid write of size 4
==18904==    at 0x400931: MAIN__ (foo.f90:9)
==18904==    by 0x400A52: main (foo.f90:13)
==18904==  Address 0x5bb3420 is 16 bytes before a block of size 320 alloc'd
==18904==    at 0x4C264B2: malloc (vg_replace_malloc.c:236)
==18904==    by 0x400904: MAIN__ (foo.f90:8)
==18904==    by 0x400A52: main (foo.f90:13)
==18904== 
==18904== Invalid read of size 4
==18904==    at 0x4F07368: extract_int (write.c:450)
==18904==    by 0x4F08171: write_integer (write.c:1260)
==18904==    by 0x4F0BBAE: _gfortrani_list_formatted_write (write.c:1553)
==18904==    by 0x40099F: MAIN__ (foo.f90:10)
==18904==    by 0x400A52: main (foo.f90:13)
==18904==  Address 0x5bb3420 is 16 bytes before a block of size 320 alloc'd
==18904==    at 0x4C264B2: malloc (vg_replace_malloc.c:236)
==18904==    by 0x400904: MAIN__ (foo.f90:8)
==18904==    by 0x400A52: main (foo.f90:13)
老街孤人 2025-01-05 16:55:57

没有错误。您将 indp 声明为具有一定范围和精度的整数(特定KIND <-在该术语的帮助中查找),可以是正数或负数。

之后,您将 1 的值分配给 t1(indp) 并将其写出。

There is no error. You declared indp as an integer of a certain range and precision (of a certain KIND <- look up in help for that term), which can be either positive or negative.

After that you assigned the value of 1 to an t1(indp) and wrote it out.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文