- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Assigning a slice of an allocatable character string onto the character string itself produces garbage sometimes:
CHARACTER(LEN = :), ALLOCATABLE :: S
S = 'TESTING'
S = S(3:)
Garbage *doesn't* appear if the character string is not allocatable. Garbage doesn't appear also if assignment is done via another variable.
I'm using Intel Visual Fortran Compiler Professional for applications running on IA-32, Version 11.1 Build 20091130 Package ID: w_cprof_p_11.1.054. This behaviour has been tested also on the latest Intel Visual Fortran Compiler, in which case the behaviour was different but still not as one would expect.
Here is a small program to demonstrate the effect.
PROGRAM ASSIGNMENT_TEST
CHARACTER(LEN = 20) :: TEST_DATA
INTEGER :: SKIP = 3
TEST_DATA = '1234567890ABCDEFGHIJ'
DO I = SKIP, 9
CALL TESTS(I)
END DO
CONTAINS
SUBROUTINE TESTS(I)
INTEGER :: I
CHARACTER(LEN = :), ALLOCATABLE :: S
! Write dummy data to S to reveal what is copied where
S = 'abcdefghijklmnopqrst'
S = TEST_DATA(1:I)
WRITE (*,*) 'S LENGTH = ', LEN(S)
WRITE (*,*) 'S : ', S
WRITE (*,*) 'Expected : ', S(SKIP:)
S = S(SKIP:)
WRITE (*,*) 'Actual : ', S
WRITE (*,*)
END SUBROUTINE TESTS
ENDPROGRAM ASSIGNMENT_TEST
When run, the program outputs the following. Note differences with string lengths 6 and 7:
S LENGTH = 3
S : 123
Expected : 3
Actual : 3
S LENGTH = 4
S : 1234
Expected : 34
Actual : 34
S LENGTH = 5
S : 12345
Expected : 345
Actual : 345
S LENGTH = 6
S : 123456
Expected : 3456
Actual : 545f
S LENGTH = 7
S : 1234567
Expected : 34567
Actual : 5f5fg
S LENGTH = 8
S : 12345678
Expected : 345678
Actual : 345678
S LENGTH = 9
S : 123456789
Expected : 3456789
Actual : 3456789
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
------
Wendy
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here is a simpler example:
[fortran] program tstThe output from Ifort 11.1.072 on Linux x64 is
character(len=:), allocatable :: S
S='abcdef'
S=S(3:)
write(*,'("|",A,"|",I2)')S,LEN(S)
S='abcdef'
S(1:)=S(3:)
write(*,'("|",A,"|",I2)')S,LEN(S)
end program tst
[/fortran]
[bash]|| 4The first result line should have been
|cdef | 6
[/bash]
|cdef| 4
This shows both the differences in the resulting string length and the bug in the Intel compiler. For the assignment on line 4, F2003 rules require that the compiler emit code to keep a copy of the r.h.s. expression as needed to avoid using deallocated memory (the old allocation of S) after reallocation of S, which is done before copying the expression into it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
S=S(SKIP:)
?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@anthonyrichards: Because that's what the deferred-length character (i.e., CHARACTER(LEN=:), ALLOCATABLE :: S) should do. the The deferred-length character feature is based on the reallocation on assignment (a Fortran 2003 feature), which means the left-hand side must always be deallocated and reallocated again to the length of the right-hand side, except when a stride is used (as in your example, S(:) ).
In Intel's implementation, reallocation on assignment is disabled by default, except for character(:) variables ---and allocatable components of derived types, I guess.
@vvnurmi: In the past, I reported a similar problem, with substrings not being handled properly ---it's not exactly the same problem, except if you think it in terms of Fortran's INTERFACE ASSIGNMENT (e.g., as if the assignment were expressed as a call to some internal subroutine).
As a workaround, you can add an empty string at the end, e.g.:
[fortran]S = S(SKIP:)//''[/fortran]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please see Sec. 7.4.1.3, especially Note 7.35, in the F2003 standard draft, J3/04-007, to which a link is located at the top of this forum. Or see Sec. 17.5.2 of Metcalf, Reid and Cohen, Fortran 95/2003 Explained, OUP, 2006. It is clear that "vvnurmi" was posting about this F2003 feature.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
------
Wendy
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As I said before, I just thought of the assignment as a call to a subroutine (e.g., s_assign_s(lhs, rhs) ). So, forcing a copy of the second argument seemed like the obvious thing to do.
That's analogous to the trick of ensuring a null-terminated buffer when dealing with the Windows API (e.g., TRIM(string)//''C ). So maybe that's why there's no optimization in that regard.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page