- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please look at this sample snippet:
PROGRAM TEST
real *4 A,B,C
call newsub1(10,20,c)
write (*,'(3e12.5)') A,B,C
stop
end
subroutine newsub1(a,b,c)
real*8 a,b,c
intent(in) :: a,b
intent(out) :: c
c = a+b
return
end
I did the followingexercise to understand the behavior of undefineable constant in the subroutine.
Infact, this program will give compile error with /gen-interface option. I suppressed this to check the
behavior of the constants inside the subroutine. Nothing gets copied in temporary storage and hence
the value of 'c' is garbage. Also the behavior is not altered by the keyword INTENT.
Please throw some light!
Thanks
Praba
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here's what happens.
The main program passes the addresses of two integer constants and a REAL*4 variable. The subroutine thinks that the integer constants are REAL*8 and fetches the 8 bytes at the locations of the constants, treating the found bytes as REAL*8. This yields some very different and not necessarily predictable REAL*8 value. Not predictable because you don't know what follows the integer value in memory.
These garbage values are then added and stored in C. But in the subroutine, C is REAL*8 so the value stored is 8 bytes, overwriting C and whatever followed it. This value is not valid as a REAL*4 because of the different exponent width.
INTENT has nothing to do with this, and I don't see what "undefinable constants" has to do with it either as you don't store to the constants. If you did, you'd probably get an asccess violation. There is an option, /assume:noprotect_constants, that will cause a writable copy of the constants to be passed.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
> Nothing gets copied in temporary storage and hence the value of 'c' is garbage.
The first part of this sentence, be it correct or not, does not lead to the second part.
Produce the assembly listing using the /Fa compiler option to see what the compiler does. Note that other compiler options can affect the behavior of buggy code, so you should not presume that the same kind of errors in code will always produce the same buggy behavior in the EXE.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am able to see the contents copied into the subroutine args for newsub1 & newsub2.
I followed the old style in newsub3 which does not work. Please explain!
PROGRAM TEST
REAL*8 c8
REAL*4 c4
integer *4 ic
call newsub1(10,20,ic)
call newsub2(10.0,20.0,c4)
call newsub3(10.0d0,20.0d0,c8)
stop
end
c
subroutine newsub1(ia,ib,ic)
integer*4 ia, ib, ic
ic = ia+ib
return
end
subroutine newsub2(a,b,c)
real*4 a,b,c
c = a+b
return
end
subroutine newsub3(a,b,c)
real*8 a,b,c
c = a+b
return
end
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I compiled this without optimization (otherwise the whole program would have been evaporated) and looked at the assembly code. The code that calls each of the routines operates exactly the same way.
[plain].B1.2: ; Preds .B1.9 add esp, -12 ;9.6 mov DWORD PTR [esp], OFFSET FLAT: __NLITPACK_1 ;9.6 mov DWORD PTR [4+esp], OFFSET FLAT: __NLITPACK_2 ;9.6 lea eax, DWORD PTR [-16+ebp] ;9.6 mov DWORD PTR [8+esp], eax ;9.6 call _NEWSUB1 ;9.6 ; LOE .B1.10: ; Preds .B1.2 add esp, 12 ;9.6 ; LOE .B1.3: ; Preds .B1.10 add esp, -12 ;11.6 mov DWORD PTR [esp], OFFSET FLAT: __NLITPACK_3 ;11.6 mov DWORD PTR [4+esp], OFFSET FLAT: __NLITPACK_4 ;11.6 lea eax, DWORD PTR [-12+ebp] ;11.6 mov DWORD PTR [8+esp], eax ;11.6 call _NEWSUB2 ;11.6 ; LOE .B1.11: ; Preds .B1.3 add esp, 12 ;11.6 ; LOE .B1.4: ; Preds .B1.11 add esp, -12 ;13.6 mov DWORD PTR [esp], OFFSET FLAT: __NLITPACK_5 ;13.6 mov DWORD PTR [4+esp], OFFSET FLAT: __NLITPACK_6 ;13.6 lea eax, DWORD PTR [-8+ebp] ;13.6 mov DWORD PTR [8+esp], eax ;13.6 call _NEWSUB3 ;13.6[/plain]Each one creates space on the stack for the argument list of addresses, moves the addresses of the arguments to the respective locations, and calls the routines. In the case of the constants, the addresses are of "materialized literals" in static memory locations.
What is it that concerns you? What are you trying to show?
Lastly, if you want to paste code, please use the code insertion tool (yellow pencil icon) to preserve formatting.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What do you mean by "old style"? What do you mean by "does not work"? Your program does not do any output. Therefore, you need to do some explaining first. What is it that you expect, in the context of which "does not work" makes some sense?
You need to report the compiler version and options used to compile.
Add this before the STOP statement:
write(*,*)ic,c4,c8
Compile, link and run the program again and see what you get.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[bash]Here is the little background about my problem.... I was porting some legacy code. The results are different with intel compiler and pgf77 in Linux. When I trace back, I realize that the arguments (some are constants) are being treated differently in pg compiler. Hence I am doing memory debug to see the argument transfer with intel debugger. I created the above sample program for discussion. I am able to see (1) integer values 10 & 20 in Memory debugger for newsub1. (2) real*4 values (10.0 & 20.0) are communicated for a & b in debugger. (3) real*8 values (0.0 & 0.0) are communicated for a & b in debugger. Legacy code writers use DEXP(), DSQRT(), 1.0d0 etc for double precision. Hence I used "call newsub3(10.0d0,20.0d0,c8)". But inside the function newsub3, the debugger shows the values for 'a' & 'b' as '0.0' & '0.0'. If I use variables as arguments, I can ensure the type consistency between the caller and called function. If I have constants (though I do not redefine them inside the function), I did not get the correct data type in the called function. I looked into my compile option... /nologo /debug:full /Od /fpp /I"C:Program FilesIntelCompiler11.072fortranmklinclude" /I"C:Program FilesVNIimslfnl600IA32includeDLL" /I"C:Program FilesVNIimslfnl600IA32includeSTATIC" /double_size:128 /module:"Debug\" /object:"Debug\" /traceback /check:bounds /check:arg_temp_created /libs:static /threads /dbglibs /c After removing "/double_size:128", I am able to get proper data type transfer ... It is my bad! Thanks for your time! [/bash]

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