- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
program testprj_fortran
implicit none
double precision:: d1(12)=(/1,2,3,4,5,6,7,8,9,0,0,0/)
call swap(d1,d1)
write(*,*) d1
read(*,*)
end program testprj_fortran
subroutine swap(dm1,dm2)
DOUBLE PRECISION DM1(12),DM2(12),DMH(9)
DMH(1)=DM1(1)
DMH(2)=DM1(4)
DMH(3)=DM1(7)
DMH(4)=DM1(2)
DMH(5)=DM1(5)
DMH(6)=DM1(8)
DMH(7)=DM1(3)
DMH(8)=DM1(6)
DMH(9)=DM1(9)
DM2(10)=DMH(1)*DM1(10)
DM2(11)=DMH(2)*DM1(10)
DM2(12)=DMH(3)*DM1(10)
DO I=1,9
DM2(I)=DMH(I)
enddo
END
gives following output in Debug-Mode or when /Od is used (this is the correct result)
1.00000000000000 4.00000000000000 7.00000000000000
2.00000000000000 5.00000000000000 8.00000000000000
3.00000000000000 6.00000000000000 9.00000000000000
0.000000000000000E+000 0.000000000000000E+000 0.000000000000000E+000
but this in Release-Mode (which is wrong)
1.00000000000000 4.00000000000000 7.00000000000000
2.00000000000000 5.00000000000000 8.00000000000000
7.00000000000000 8.00000000000000 9.00000000000000
0.000000000000000E+000 0.000000000000000E+000 0.000000000000000E+000
I tried this with compiler versions 11.1.64, 11.1.60, 11.1.51, 11.0.74 and 10.1.25. All compilers give the same result.
My Compiler Options in Release-Mode are:
/nologo /module:"Release\\\\" /object:"Release\\\\" /libs:static /threads /c
What is wrong? Any Ideas?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The optimiser 'knows' that arrays will not overlap, so it recognises that DMH is an unneeded temporary array, and refactors to work directly with DM1 and DM2. This is why you get duplicates for 7 & 8. At different optimisation levels you might get different duplicates. You might be better off writing it as a function that returns an array.
FUNCTION swap(d1) RESULT (d2)
REAL:: d2(UBOUND(d1)) ! Whatever is the correct syntax
...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That section places limits on what can be done to dummy arguments that are associated with the same (part of an) actual argument, without there being things like TARGET/POINTER attributes etc - you can't define any part of the dummy arguments that overlap. I think you are breaking those limits. All bets are off.
An alternative work around to the (possibly better) function call suggestion would be to change the call to be:
[fortran]call swap((d1),d1) [/fortran]where the first dummy argument is then associated with an actual argument that is an expression (that happens to involve d1) and not directly to the variable d1. I think your code would then be standard conforming.
Implementation detail (?) - but when the compiler sees the expression "(d1)" it will probably create a temporary array, fill that temporary with the value of d1 (as per the expression) and then call the swap procedure. The function call approach may also result in the creation of a temporary array, but it may avoid the need to fill (copy) the temporary with the value of d1 prior to the call. Regardless of that detail (and note that the optimiser may be smart enough to avoid temporaries and copies anyway) as the code with the expression or function call becomes standard conforming you can rely on the overall behaviour, which would be as you originally expected.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have read chapter 12.4.1.7 of ISO/IEC FCD 1539-1:2004(E) (hope that's the document your refered to) but I can not see what it has to do with my example. Chapter 12.4.1.7 deals with references to outer defined variables (which is not the case in my example) and with defining, redefining and undefinig of arguments (which is also not done in my example). To avaid missunderstanding change swap to
subroutine swap(dm1,dm2)
DOUBLE PRECISION DM1(12),DM2(12),DMH(10)
DMH(1)=DM1(1)
DMH(2)=DM1(4)
DMH(3)=DM1(7)
DMH(4)=DM1(2)
DMH(5)=DM1(5)
DMH(6)=DM1(8)
DMH(7)=DM1(3)
DMH(8)=DM1(6)
DMH(9)=DM1(9)
DMH(10)=DM1(10)
DM2(10)=DMH(1)*DMH(10)
DM2(11)=DMH(2)*DMH(10)
DM2(12)=DMH(3)*DMH(10)
DO I=1,9
DM2(I)=DMH(I)
enddo
END
You can see that there isn'tan overlap of the dummy arguments during the assignments. But this example also fails.
DMH in swap was only added to make swap callablewith the same arguments and as far as I understand the FORTRAN Standard this has to be allowed. I think the optimizer of the FORTRAN Compiler did too much.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Assignment is one way of defining a variable. Because you have two dummy arguments (dm1 and dm2) associated with the same entity (d1) (and the dummies don't have target/pointer attributes etc) you cannot assign to any part of either of them. The order of assignments doesn't matter and the presence of the DMH variable doesn't matter.
This restriction on aliasing is a Fortran language feature as it allows (or simplifies) certain optimisations.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I see you are absolutly right. Because of my restricted knowledge of the english language I didn't realize that 'define' included 'assign'.
It's surprising that this 'error' does not appear if 'I don't assign values to DM2(10:12) and that these assignments destroy DM2(1:9)!
I have lots of F77 programs where this type of argument passing is done. In most cases this works without any error. Is there a rule when this type of argument passing fails?
In F77 this was common practice so I think this restriction came with F90,F95 or F2003. Does someone know?
- 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
In the Northern latitudes this is what we would call "Walking on thin ice". The fact that you have walked across a frozen pond does not assure you that it is safe to walk across that frozen pond. (does not assure that the ice is thick enough to safely walk across).
>>It's surprising that this 'error' does not appear if 'I don't assign values to DM2(10:12) and that these assignments destroy DM2(1:9)!
This is a case where the 'symptom' of the programming error does not appear. (or had not appeared for a long time)
Another way to think of this is a single threaded analog of what occures in a multi-threaded race condition. The way the code was written, the compiler was free to rearrange the statements to produce the stated results. Or you could say the compiler had more liberties than you assumed/experienced.
If you have many such subroutines/functions that have this problem then by disabling optimizations for these subroutines/functions may reduce/eliminate the 'symptom' although it will not correct the programming error.
If you want the optimizations for the cases when the dummy args do not overlap, yet permit occasional calls with overlappingdummies, then you will need to insert a test for overlapping dummies .or. create a new function/subroutine where you test for same dummies, overlapping dummies, non-overlapping dummies.
Jim Demspey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
"computing's central challenge, viz. 'How not to make a mess of it', has not been met"
That dictum applies very well here.
That you have code in which some rules of Fortran were broken yet worked correctly has the hallmarks of a self-made trap. There is no guaranteed penalty (i.e., wrong results) for writing buggy code. However, escaping from penalty is not guaranteed, either.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Alas when working with legacy libraries, some 25+ years old, these things crop up.
Just this week I found the same problem
subroutine trans(matrix, inar, outar)
calculate tempar as function of matrix and inar
assign tempar to outar
end
call trans(mat, p1, p1)
appeared in lots of places
Interestingly :
32bit debug and release worked ok
64bit debug worked ok
64bit release failed :-(
It took me several days to track down the problem (using print statements)especially as debug 64bit worked.
No doubt there are other pieces of code doing similar things waiting to trip me up.
Les
PS
Microsoft have put further obstacles inmy way by not allowing debugging of mixed (managed and unmanaged) code for 64bit compilation in VS2008.
Ihaven't been able tofind out if this restrictionis removed in VS2010
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Microsoft have put further obstacles inmy way by not allowing debugging of mixed (managed and unmanaged) code for 64bit compilation in VS2008.
Ihaven't been able tofind out if this restrictionis removed in VS2010
Yes, that's a pain. However, it is not allowed only to debug them simultaneously (in the same debug session). If you want to debug only an unmanaged component, set it as a startup project, and set up the managed .exe as the "executable for debug session". Additionally, make sure that the debugger model in project settings is "Native only" (rather than "Automatic").
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Microsoft have put further obstacles inmy way by not allowing debugging of mixed (managed and unmanaged) code for 64bit compilation in VS2008.
Ihaven't been able tofind out if this restrictionis removed in VS2010
Microsoft appears to claim that this works in VS 2010 if the .NET code uses the .NET Framework 4.0. I have not yet been able to verify this.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page