这样使用字符串指针安全吗?
Is this use of character string pointers safe?
在实现字符串实用函数时,我遇到了几个我认为可能不安全的字符指针表达式。我用谷歌搜索,搜索 SO,阅读我的 Fortran 95 语言指南(Gehrke 1996)以及 Google 书中展示的各种摘录。但是,我找不到任何讨论此特定用法的资源。
ifort 和 gfortran 都会在没有警告的情况下编译以下程序:
PROGRAM test_pointer
IMPLICIT NONE
CHARACTER(LEN=100), TARGET :: string = "A string variable"
CHARACTER(LEN=0), TARGET :: empty = ""
CHARACTER(LEN=:), POINTER :: ptr
ptr => NULL()
IF(ptr == "") PRINT *, 'Nullified pointer is equal to ""'
ptr => string(-2:-3)
IF(ptr == "") PRINT *, 'ptr equals "", but the (empty) sub string was out of bounds.'
ptr => empty(1:0)
IF(ptr == "") PRINT *, 'ptr equals "", it was not possible to specify subarray within bonds'
END PROGRAM
程序的输出是:
Nullified pointer is equal to ""
ptr equals "", but the (empty) sub string was out of bounds.
ptr equals "", it was not possible to specify subarray within bonds
显然,指针的求值对编译器来说是有意义的,并且结果是您所期望的。有人可以解释为什么上面的代码没有导致至少一个分段错误吗?该标准是否真的允许越界子串?使用无效字符指针怎么样?
编辑: 阅读 Vladimir F 的回答后,我意识到我忘记激活 运行时间检查。无效指针实际上会触发 运行 时间错误。
为什么它们不会导致段错误?取消引用无效指针不符合标准(在 C 术语中它是 未定义的行为)。该标准没有说明不合格的程序应该做什么。该标准仅适用于符合它的程序!对于不合格的程序,任何事情都可能发生!
我明白了(sunf90):
****** FORTRAN RUN-TIME SYSTEM ******
Attempting to use an unassociated POINTER 'PTR'
Location: line 8 column 6 of 'charptr.f90'
Aborted
和另一个编译器(ifort):
forrtl: severe (408): fort: (7): Attempt to use pointer PTR when it is not associated with a target
Image PC Routine Line Source
a.out 0000000000402EB8 Unknown Unknown Unknown
a.out 0000000000402DE6 Unknown Unknown Unknown
libc.so.6 00007FA0AE123A15 Unknown Unknown Unknown
a.out 0000000000402CD9 Unknown Unknown Unknown
另外两次访问,你没有访问任何东西,你创建的是一个长度为0的子串,不需要访问字符变量,结果只是一个空字符串。
具体来说,Fortran 标准 (F2008:6.4.1.3) 关于创建子字符串的说明如下:
Both the starting point and the ending point shall be within the
range 1, 2, ..., n unless the starting point exceeds the ending
point, in which case the substring has length zero.
因此第一部分不符合标准,但其他部分符合标准。
在实现字符串实用函数时,我遇到了几个我认为可能不安全的字符指针表达式。我用谷歌搜索,搜索 SO,阅读我的 Fortran 95 语言指南(Gehrke 1996)以及 Google 书中展示的各种摘录。但是,我找不到任何讨论此特定用法的资源。
ifort 和 gfortran 都会在没有警告的情况下编译以下程序:
PROGRAM test_pointer
IMPLICIT NONE
CHARACTER(LEN=100), TARGET :: string = "A string variable"
CHARACTER(LEN=0), TARGET :: empty = ""
CHARACTER(LEN=:), POINTER :: ptr
ptr => NULL()
IF(ptr == "") PRINT *, 'Nullified pointer is equal to ""'
ptr => string(-2:-3)
IF(ptr == "") PRINT *, 'ptr equals "", but the (empty) sub string was out of bounds.'
ptr => empty(1:0)
IF(ptr == "") PRINT *, 'ptr equals "", it was not possible to specify subarray within bonds'
END PROGRAM
程序的输出是:
Nullified pointer is equal to ""
ptr equals "", but the (empty) sub string was out of bounds.
ptr equals "", it was not possible to specify subarray within bonds
显然,指针的求值对编译器来说是有意义的,并且结果是您所期望的。有人可以解释为什么上面的代码没有导致至少一个分段错误吗?该标准是否真的允许越界子串?使用无效字符指针怎么样?
编辑: 阅读 Vladimir F 的回答后,我意识到我忘记激活 运行时间检查。无效指针实际上会触发 运行 时间错误。
为什么它们不会导致段错误?取消引用无效指针不符合标准(在 C 术语中它是 未定义的行为)。该标准没有说明不合格的程序应该做什么。该标准仅适用于符合它的程序!对于不合格的程序,任何事情都可能发生!
我明白了(sunf90):
****** FORTRAN RUN-TIME SYSTEM ******
Attempting to use an unassociated POINTER 'PTR'
Location: line 8 column 6 of 'charptr.f90'
Aborted
和另一个编译器(ifort):
forrtl: severe (408): fort: (7): Attempt to use pointer PTR when it is not associated with a target
Image PC Routine Line Source
a.out 0000000000402EB8 Unknown Unknown Unknown
a.out 0000000000402DE6 Unknown Unknown Unknown
libc.so.6 00007FA0AE123A15 Unknown Unknown Unknown
a.out 0000000000402CD9 Unknown Unknown Unknown
另外两次访问,你没有访问任何东西,你创建的是一个长度为0的子串,不需要访问字符变量,结果只是一个空字符串。
具体来说,Fortran 标准 (F2008:6.4.1.3) 关于创建子字符串的说明如下:
Both the starting point and the ending point shall be within the range 1, 2, ..., n unless the starting point exceeds the ending point, in which case the substring has length zero.
因此第一部分不符合标准,但其他部分符合标准。