06-29-2011 11:41 AM
I am in the process of migrating our code base from Alpha to Itanium and I have a defined function not returning proper results on the Itanium. This function works properly on the Alpha.
The alpha environment I am running this on is
VMS version 7.3-1, Basic 1.5
I am porting to
Itanium VMS version 8.3-1H1, Basic version 1.7
When the code executes it seems to have the proper value at the end of the function and when the system passes the parameter back the string is always empty.
The function is locally defined in the program executing it.
One thing I have noticed is debugger will not allow me to evaluate R1$, I receive the error "no access to address".
I set the R1$ to another local variable to examine the contents just before the parameter is passed back and the results are what I am expecting.
Any suggestions would be greatly appreciated.
Solved! Go to Solution.
06-29-2011 12:28 PM
I will admit that I have not used Basic in a while, but the following appears to be incorrect:
You are referencing REC$ within the function. REC$ is the passes parameter and within the function itself, the variable that should be used is R1$. Is the confusion due to a "local" variable within the function also called REC$ that is causing this problem? I don't have the Basic compiler to confirm, but a crossreference listing should indicate whether or not REC$ is actually two separate memory locations.
06-29-2011 02:42 PM
I'd try recoding the function as a procedure returning the value as the first parameter instead of as a function value, just to check that you can pass it back to the caller. Note that is exactly how the VAX procedure calling standard would have implemented the call, as only scalar types could be returned in registers.
Next simplify the function, for example, try:
DEF FNREAD$ ( STRING R1$ ) FNREAD$ = R1$ FNEND
which is probably simple enough to try to follow it in machine code to see how the routine thinks it's returning a value, and where the caller is looking for it. Some judicious debug watchpoints might help too.
I don't have a compiler to experiment with. In my experience, Basic has a nasty habit of performing numerous hidden data conversions, which sometimes cause values to change unexpectedly. They are usually "correct" from the compilers perspective, but unexpected by the programmer. You appear to be doing the right thing to minimises surprises, using specific data type suffixes everywhere.
re: unable to examine a variable... are you compiling /DEBUG/NOOPTIMIZE?
06-29-2011 11:05 PM
Seems to work for me using I64 BASIC V1.7-000
I changed the provide program (why a sill DOC file??? why not good old TXT !!!) to read:
1 !Call to Function
REC$ = "aaaaa.bbbbb;ccccc "
option_piece$ = FNREAD$ ( REC$ )
Compile, link, run ... "bbbbb"
As pointed out, the function seems to freely use data scoped in 'main' and in the 'function'.
Specifically I don't like seeing REC$ used when R1$ is passed with the the value of REC$.. in the example.
Are you sure each call to FNREAD$ passes REC$. Maybe REC$ was empty on entry?? Check with debugger!
I am also not a fan of modifying my function argument.
I suppose that's legal, but why not grab a fresh intermediate variable?
The debugger also happily looked at the variables for me:
break at X$MAIN\X$MAIN\FNREAD$\%LINE 40X$MAIN\X$MAIN\FNREAD$\R1$: "bbbbb"X$MAIN\X$MAIN\REC$: "aaaaa.bbbbb;ccccc "
So I suspect it is an interaction with variable declarations as main level.
As suggested, compil/list and specifically look for "Allocation information for DEF FNREAD$ "
And any and all variable used in that function.
06-30-2011 12:55 PM
I wanted to thank everyone for their help and suggestions.
I have found what is causing my error. I don't know why and would love to get some help with why this is happening and how to resolve it.
This is what I have found:
The call to FNREAD$ works correctly until I call CMS$SET_LIBRARY. After the call then FNREAD$ no longer passes back the expected results. It is always passing back an empty string.
I get the same results whether I compile with nooptimize or optimize=level=4
I have created and attached a program that re-produces the error.
Again, any suggestions would be great.
06-30-2011 02:32 PM - edited 06-30-2011 02:51 PM
Now we're cooking with gas!
Ayup that reproduces, even without library present.
Surely a memory overwrite.
If you double the CMS LIB_DB structure in size, and/or move it away from the other variables then the program will work again.
Report with the reproducer to HP, and let them tell you want the new minimum size of LIB_DB should be.
CMS$SET_LIBRARY says it uses 57 longs, where you allocated 51.
This 'appears' to fix it:
MAP (X) LONG LIB_DB ( 50 ) ! Declaration of Library Data Block
This fixes better:
DIM LONG LIB_DB ( 99 ) ! Declaration of Library Data Block
This reports usage:
PRINT "******* ";option_piece$;" ******. LIB_DB(0)="; LIB_DB(0)
06-30-2011 02:55 PM
That symptom suggests the CMS$SET_LIBRARY call is corrupting something.
I'd also recommend getting rid of the up reference to REC$ from inside FNREAD$. I still don't understand why its there, when the same record is passed in as R1$.
I'm a bit concerned that your argument list declaration for CMS$SET_LIBRARY is not strictly correct. You've said (LONG, STRING BY DESC). The first argument is really a 50 element array by reference. If Basic has interpreted your actual argument "LIB_DB(0)" as an expression, evaluated it to a stack temporary and passed the result by reference to CMS$SET_LIBRARY, then that might account for some stack corruption.
Try changing the declaration to
(LONG BY REF, STRING BY DESC),
[or even better whatever the syntax is for "50 element LONG array by reference"]
and calling as (LIB_DB ,cms_library)
It pays to be very precise when declaring argument lists. Depending on optimisation, some compilers might realise that the expression "LIB_DB(0)" could be satisfied by using the actual address of the array element, which would behave exactly as if the array were passed by reference. A different compiler which evalulates the expression to a temporary location would behave differently. That might explain why this code may have "worked" on Alpha but behaves differently on Itanium (do any of the subsequent CMS$ calls work on Itanium?)
07-01-2011 06:40 AM
Thanks Hein and John for all your help and suggestions!!
I have submitted this to HP to get the minimum size the the lib data block.
I also have updated the code and removed all references to REC$ in the function as John suggested.