为什么在清晰写入数组边界时没有运行时错误? [英] Why no runtime error when clearly writing over array bounds?

查看:218
本文介绍了为什么在清晰写入数组边界时没有运行时错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个程序,它分配了一个超出其范围的数组,并且我期待着抛出一个运行时错误。然而,没有任何错误发生,程序继续写入未声明的内存。有没有一些编译器选项来防止这种情况发生?显示内存转储清楚地表明这种边界的超越是真实的。有没有办法声明变量或参数规格来捕捉这个?很明显,这是一个明确的例子,但是当承担维护数千行F77派生代码的责任时,如果可能发生这种情况,并不总是很清楚。

  PROGRAM TEST_CODE 
IMPLICIT NONE

INTEGER * 4 :: R(5)!数组5

CALL R_TEST(R,10)

结束程序

子程序R_TEST(R,J)
隐含无

INTEGER * 4,INTENT(INOUT):: R(1)! Dummy是数组1
INTEGER * 4,INTENT(IN):: J
INTEGER * 4 :: K

DO K = J-5,J + 5! K = 5..15
R(K)= K!没有运行时错误
END DO

END SUBROUTINE

编译器是英特尔Fortran 2011 XE,是的,我使用字节规格 INTEGER * 4 ,因为我知道我得到了什么。



以下是用于运行时检查的编译器选项。



解决方案

intel编译器在指针和可分配数组的边界检查方面做得非常好。如果你稍微修改你的代码(下面)并编译如下:

$ ifort -O0 -debug -traceback -check -ftrapuv TEST_CODE.f90



您将得到运行时错误。但是对于假定的大小数组,intel编译器无法检查边界。特别是对于使用隐式键入的F77代码等,找到内存泄漏并不容易。 Fortran中的另一个小东西,你的程序必须做一些有意义的事情;否则编译器会忽略你的代码,因为它什么都不做!这就是为什么我最终添加了一个打印。



R(:)的一个小问题是编译器不能假定它在内存中是连续的;因此它不能进行一些编译器优化。使用可分配数组或使用连续属性(F2008标准)会更好。

  PROGRAM TEST_CODE 
IMPLICIT NONE

INTEGER * 4 :: R(5)!数组5

CALL R_TEST(R,10)
print *,R

结束程序

子程序R_TEST(R,J )
IMPLICIT NONE

INTEGER * 4,INTENT(INOUT):: R(:)! Dummy是数组1
INTEGER * 4,INTENT(IN):: J
INTEGER * 4 :: K

DO K = J-5,J + 5! K = 5..15
R(K)= K!没有运行时错误
END DO

END SUBROUTINE


I have a program that assigns an array beyond it's bounds, and I was expecting a run-time error to be thrown. Yet no error is raised at all and the program proceeds to write into undeclared memory. Is there some compiler option to guard against this? With the memory dump shown it is clear this overreach of bounds is real. Is there a way to declare variables or argument specs to catch this? Obviously this is a clear case, but when tasked to maintain thousands of lines of F77 derived code it is not always clear (to me) if this might be happening.

PROGRAM TEST_CODE
IMPLICIT NONE

INTEGER*4 :: R(5)           ! Array of 5

    CALL R_TEST(R, 10)

END PROGRAM

SUBROUTINE R_TEST(R, J)
IMPLICIT NONE

INTEGER*4, INTENT(INOUT) :: R(1)    ! Dummy is array of 1
INTEGER*4, INTENT(IN) :: J
INTEGER*4 :: K

DO K=J-5,J+5            ! K=5..15
    R(K) = K            ! No Runtime Error
END DO

END SUBROUTINE

Compiler is Intel Fortran 2011 XE, and yes I am using the byte spec INTEGER*4 because I know what I get with it.

Here are the compiler options for runtime checking.

解决方案

The intel compiler does a very good job on bounds checking for the pointer and allocatable arrays. If you slightly modify your code (below) and compile with something like:

$ ifort -O0 -debug -traceback -check -ftrapuv TEST_CODE.f90

you will get a run time error. But for assumed size arrays the intel compiler cannot check the bounds. Especially for F77 codes with implicit typing and so on it won't be easy to find memory leaks. Another tiny thing, in Fortran your program has to do something meaningful; otherwise the compiler will omit your code because it simply does nothing! That's why I added a print in the end.

There is a small problem with R(:) thing is that the compiler cannot assume that it is contiguous in the memory; hence it cannot make some compiler optimization. It would then be better to use allocatable arrays or use the contiguous attribute (F2008 standard).

PROGRAM TEST_CODE
IMPLICIT NONE

INTEGER*4 :: R(5)           ! Array of 5

    CALL R_TEST(R, 10)
    print *,R

END PROGRAM

SUBROUTINE R_TEST(R, J)
IMPLICIT NONE

INTEGER*4, INTENT(INOUT) :: R(:)    ! Dummy is array of 1
INTEGER*4, INTENT(IN) :: J
INTEGER*4 :: K

DO K=J-5,J+5            ! K=5..15
    R(K) = K            ! No Runtime Error
END DO

END SUBROUTINE

这篇关于为什么在清晰写入数组边界时没有运行时错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆