I have a CICS web service and in one step I move 0 to many comp-5 variables. The problem that we have come across is that sometimes it gives ASRA and in Abend Aid we can see "Protection Exception" if the same details are requested again it works perfectly fine. We are not able to figure out why it fails sometimes and goes fine other times.
The physical address of destination field for MOVE statement is calculated as:
(destination) = (array_start_address) + (element_size_in_bytes) * (index_value - lowest_index)
If index_value is outside of the range lowest_index...highest_index, then calculated physical address is outside of the memory chunk allocated for the whole array. Two results are possible (randomly):
1) This memory outside of this range may be still available to your program, but very likely you will accidentally override unexpected value(s) of other variables/fields/records/whatever.
2) This memory outside of the array is not allocated to your program, and that's why it is protected by memory access key. This situation for sure is causing "Protection exception" (e.g. ABEND S0C4/S0C5, etc.)
content of the merged post follows
It depends on the particular compiler how to handle the order of operations in the single MOVE
The A can be initialized to 0 either before, or after calculating the destination D(A), etc. There is a good chance that uninitialized (garbage) value of A is used to point to D(A)
Joined: 09 Mar 2011 Posts: 7312 Location: Inside the Matrix
For a data-name used as a subscript, the address referened will be the start of the table plus (the length of the table item multiplied by ( value in data-name mnus one).
If the value in your data-name is zero (for A in your example, and I hope that is not a real name) then the storage you access is outside your table.
If your table is in "acquired" storage (GETMAIN, for instancce) and it is at the beginning of that storage, then whether you get an abend (protection exception) or "just" squish something else in error depends entirely on whether the storage accessed in error is "yours" or not.
how arrays are defined and arranged in storage depend ONLY on the language and not on the environment ( computer/whatever architecture )
a11 a12 a13
a21 a22 a23
can be stored in
e.g., Fortran, ...
a11 a21 a12 a22 a13 a23
e.g C/C++/Objective-C (for C-style arrays), Mathematica, PL/I, ...
a11 a12 a13 a21 a22 a23
<sparse> or whatever jargon the language uses
e.g Swift, Java, ...
the elements in the same row are contiguous (like row-major order),
but not the rows.
for large arrays on ancient <systems> where the cache allcation was pretty primitive
( modulo <something> the real storage address IIRC )
accessing it in the wrong order
would put a lot of strain the cache
every inner index increment would cause a cache-frame fetch from storage
tested on an IBM 3090 200
just filling an array with zeroes
Joined: 06 Jun 2008 Posts: 8561 Location: Dubuque, Iowa, USA
I think the issue is because we are moving 0 to variable(0).. and arrays in mainframe start from 1. but then why does it not fail every time?
What you think is almost certainly wrong. Variable(0) is most likely part of your program memory and hence would not cause a protection exception. From the Enterprise COBOL Language Reference manual:
If the sending field (identifier-1) is reference-modified or subscripted, or is an alphanumeric or national function-identifier, the reference-modifier, subscript, or function is evaluated only once, immediately before data is moved to the first of the receiving operands.
Any length evaluation, subscripting, or reference-modification associated with a receiving field (identifier-2) is evaluated immediately before the data is moved into that receiving field.
For example, the result of the statement:
MOVE A(B) TO B, C(B).
is equivalent to:
MOVE A(B) TO TEMP.
MOVE TEMP TO B.
MOVE TEMP TO C(B).
where TEMP is defined as an intermediate result item. The subscript B has changed in value between the time that the first move took place and the time that the final move to C(B) is executed
However, if A does not have a value before your MOVE is executed, depending upon the specific code being used it is possible that you are referencing a random memory location, which may not be part of your program memory and hence WOULD cause a protection exception.
Variable(0) is most likely part of your program memory and hence would not cause a protection exception.
Not because of it is "part of your program".
Variable (0) is used as read-only in MOVE statement; it cannot cause "Protection exception" at all. The ABEND S0C4 is resulted only from the attempt to store new value into protected physical memory address.
Here, probability is 99.9% that the index used to define output fields in MOVE statement is outside of allowed range.
Joined: 09 Mar 2011 Posts: 7312 Location: Inside the Matrix
How COBOL deals with this:
Move 0 To A
Is defined in the COBOL Standard. Zero will be placed in A, B, C, D using the current value of A as the subscript, so zero, so a problem, E, F with the same problem as D, and so with G, H and J. I will be zero.
The "zero" may be a different zero for any of the fields (some can be binary (of any type), packed-decimal, zoned-decimal, floating-point, it doesn't matter to the MOVE and the result will be correct - except for the zero-as-a-subscript).
Depending on the location of those items in relation to the start of the storage that is "yours" you've either squished your own storage or attempted to squish something that is not yours (so the S0C4).
Never use zero as a subscript.
Use descriptive names for data. Why scrunch things up like that? D(A). What's wrong with DESCRIPTIVE-NAME ( DESCRIPTIVE-SUBSCRIPT ).
Oh, forgetting, it is so much easier to write, and who cares if it makes it less convenient to maintain. Written once. Maintained several times. And for code like yours, probably a lot of "problem determination" as well.
Do it properly first time up. It'll save this type of thing, and save significantly over time.