View previous topic :: View next topic
|
Author |
Message |
cybertaurean
New User
Joined: 22 Dec 2008 Posts: 87 Location: US
|
|
|
|
Hi All,
Came across this interesting find related to OCCURS DEPENDING ON (still testing to find its various behaviours).
I have a data structure defined as -
Code: |
01 WS-ARRAY-1.
05 WS-ARR0 OCCURS 1 TO 10 TIMES DEPENDING ON WS-H
INDEXED BY WS-0.
10 WS-ARR00 PIC X(1).
05 WS-TEMP-1.
10 WS-TEMP-2 PIC X(1).
10 WS-TEMP-3.
15 WS-TEMP-4 PIC X(1). |
I passed a value of 06 through SYSIN in the module to WS-H (now the array would have 6 occurences) and filled them with '*' (code below)
Code: |
MOVE '1' TO WS-TEMP-2
MOVE '2' TO WS-TEMP-4
PERFORM
VARYING WS-0 FROM 1 BY 1
UNTIL WS-0 > WS-H
MOVE '*' TO WS-ARR00 (WS-0)
END-PERFORM |
On displaying the variables, I get the following result -
Code
Code: |
DISPLAY 'VALUE AT CURRENT POSITION : ' WS-ARR00 (WS-0)
DISPLAY 'WS-ARRAY-1 : ' WS-ARRAY-1 |
Output:
Code: |
VALUE AT CURRENT POSITION : 1
WS-ARRAY-1 : ******12 |
WS-0 being at the 7th position (the array has just 6) after the PERFORM VARYING probably referred to the variable WS-TEMP-2 which has a values of '1' (Strange or the obvious?)
Next I moved 10 to the DEPENDING variable WS-H and 'Q' to WS-ARR00 (10) -
Code:
Code: |
MOVE 10 TO WS-H
MOVE 'Q' TO WS-ARR00 (10)
DISPLAY 'WS-ARRAY-1 : ' WS-ARRAY-1
DISPLAY 'WS-TEMP-2 : ' WS-TEMP-2
DISPLAY 'WS-TEMP-4 : ' WS-TEMP-4 |
Output:
Code: |
WS-ARRAY-1 : ******12 Q
WS-TEMP-2 :
WS-TEMP-4 : |
giving me the following result (the array actually went over and referred to the subsequent fields (:O). But that's not my issue, the fields lost their original values ('1' and '2') -
I went on to bringing the DEPENDING variable WS-H back to zero (some kind of INITIALIZATION huh? They don't allow INITIALIZE or REDEFINE on variable blocks. The compiler would complain) -
Code:
Code: |
MOVE 0 TO WS-H
DISPLAY 'WS-ARRAY-1 : ' WS-ARRAY-1
DISPLAY 'WS-TEMP-2 : ' WS-TEMP-2
DISPLAY 'WS-TEMP-4 : ' WS-TEMP-4 |
Output:
Code: |
WS-ARRAY-1 : **
WS-TEMP-2 : *
WS-TEMP-4 : * |
Can anyone tell me what happened above? I felt it should have been '12' since all the blocks allocated for the array are nullified and the parent variable reference should have printed out '12' (if they are there). OK! let's assume they are gone at this point since the array "overran" them.
Now we start the rebuild of the array from 1 to 11 occurrence. I am listing out the changes in values one by 1 in code/output sequences -
Code:
Code: |
MOVE 1 TO WS-H
DISPLAY 'WS-ARRAY-1 : ' WS-ARRAY-1
DISPLAY 'WS-TEMP-2 : ' WS-TEMP-2
DISPLAY 'WS-TEMP-4 : ' WS-TEMP-4 |
Output:
Code: |
WS-ARRAY-1 : ***
WS-TEMP-2 : *
WS-TEMP-4 : * |
Code:
Code: |
MOVE 2 TO WS-H
DISPLAY 'WS-ARRAY-1 : ' WS-ARRAY-1
DISPLAY 'WS-TEMP-2 : ' WS-TEMP-2
DISPLAY 'WS-TEMP-4 : ' WS-TEMP-4 |
Output:
Code: |
WS-ARRAY-1 : ****
WS-TEMP-2 : *
WS-TEMP-4 : * |
Code:
Code: |
MOVE 3 TO WS-H
DISPLAY 'WS-ARRAY-1 : ' WS-ARRAY-1
DISPLAY 'WS-TEMP-2 : ' WS-TEMP-2
DISPLAY 'WS-TEMP-4 : ' WS-TEMP-4 |
Output:
Code: |
WS-ARRAY-1 : *****
WS-TEMP-2 : *
WS-TEMP-4 : * |
Code:
Code: |
MOVE 4 TO WS-H
DISPLAY 'WS-ARRAY-1 : ' WS-ARRAY-1
DISPLAY 'WS-TEMP-2 : ' WS-TEMP-2
DISPLAY 'WS-TEMP-4 : ' WS-TEMP-4 |
Output:
Code: |
WS-ARRAY-1 : ******
WS-TEMP-2 : *
WS-TEMP-4 : * |
Code:
Code: |
MOVE 5 TO WS-H
DISPLAY 'WS-ARRAY-1 : ' WS-ARRAY-1
DISPLAY 'WS-TEMP-2 : ' WS-TEMP-2
DISPLAY 'WS-TEMP-4 : ' WS-TEMP-4 |
Output:
Code: |
WS-ARRAY-1 : ******1
WS-TEMP-2 : *
WS-TEMP-4 : 1 |
Look above!!! The "lost" variables seem to be re-emerging (from bottom-up )!!!
Code:
Code: |
MOVE 6 TO WS-H
DISPLAY 'WS-ARRAY-1 : ' WS-ARRAY-1
DISPLAY 'WS-TEMP-2 : ' WS-TEMP-2
DISPLAY 'WS-TEMP-4 : ' WS-TEMP-4 |
Output:
Code: |
WS-ARRAY-1 : ******12
WS-TEMP-2 : 1
WS-TEMP-4 : 2 |
Now we back to normal self. How things were at the start of the program... All variables with their correct values! Moving on...
Code:
Code: |
MOVE 7 TO WS-H
DISPLAY 'WS-ARRAY-1 : ' WS-ARRAY-1
DISPLAY 'WS-TEMP-2 : ' WS-TEMP-2
DISPLAY 'WS-TEMP-4 : ' WS-TEMP-4 |
Output:
Code: |
WS-ARRAY-1 : ******12
WS-TEMP-2 : 2
WS-TEMP-4 : |
They start disappearing again...
Code:
Code: |
MOVE 8 TO WS-H
DISPLAY 'WS-ARRAY-1 : ' WS-ARRAY-1
DISPLAY 'WS-TEMP-2 : ' WS-TEMP-2
DISPLAY 'WS-TEMP-4 : ' WS-TEMP-4 |
Output:
Code: |
WS-ARRAY-1 : ******12 Q
WS-TEMP-2 :
WS-TEMP-4 : Q |
Code:
Code: |
MOVE 9 TO WS-H
DISPLAY 'WS-ARRAY-1 : ' WS-ARRAY-1
DISPLAY 'WS-TEMP-2 : ' WS-TEMP-2
DISPLAY 'WS-TEMP-4 : ' WS-TEMP-4 |
Output:
Code: |
WS-ARRAY-1 : ******12 Q
WS-TEMP-2 : Q
WS-TEMP-4 : |
Code:
Code: |
MOVE 10 TO WS-H
DISPLAY 'WS-ARRAY-1 : ' WS-ARRAY-1
DISPLAY 'WS-TEMP-2 : ' WS-TEMP-2
DISPLAY 'WS-TEMP-4 : ' WS-TEMP-4 |
Output:
Code: |
WS-ARRAY-1 : ******12 Q
WS-TEMP-2 :
WS-TEMP-4 : |
Code:
Code: |
MOVE 11 TO WS-H
DISPLAY 'WS-ARRAY-1 : ' WS-ARRAY-1
DISPLAY 'WS-TEMP-2 : ' WS-TEMP-2
DISPLAY 'WS-TEMP-4 : ' WS-TEMP-4 |
Output:
Code: |
WS-ARRAY-1 : ******12 Q
WS-TEMP-2 :
WS-TEMP-4 : |
Given the limitations on the array 'OCCURS 1 TO 10 TIMES', I'm surprised how the last case even worked?
Could someone take a look and explain how the allocation happened in the above execution (Note: All these are from a single run of a program)
Regards,
C.T. |
|
Back to top |
|
|
dbzTHEdinosauer
Global Moderator
Joined: 20 Oct 2006 Posts: 6966 Location: porcelain throne
|
|
|
|
no need to look.
occurs depending on only has an affect when you - issue a move from the table to another area
- SEARCH ALL
- SEARCH
all you have managed to prove is that SSRANGE(OFF) is in effect
and when you exceeded 10 occurances, you over-wrote storage following the table.
and this gobbelty-gook that you provided as code,
is only snippets,
and there is no way to follow the execution. |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8700 Location: Dubuque, Iowa, USA
|
|
|
|
Without studying your examples in detail, there are a couple of things you need to be aware of:
1. When using WORKING-STORAGE, a table defined with OCCURS DEPENDING ON will use exactly the same amount of memory as a table defined just with OCCURS. COBOL allocates memory for the table based on the maximum number of occurrences, so the memory is always there.
2. Unless you have the SSRANGE option turned on while doing the compile, COBOL does not check nor otherwise limit your table subscripts in any way. |
|
Back to top |
|
|
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
Consult the manuals.
There was also a topic a few weeks ago here, try to find that. Some file layout with ODO but minus the value. Also one to pick out CITY/STATE/ZIP from address lines. Read, try to understand with aid of manual, let us know any questions you have.
There is also some ODO in the Junk Buster :-)
Although you can define the data like that, it is your responsibility, not that of the compiler, to preserve the correct values of fields after the occurs depending on but not subordinate to it.
When you put 11 in your odo, and you don't have SSRANGE, you poked yourself into the next piece of storage, as has been said. |
|
Back to top |
|
|
cybertaurean
New User
Joined: 22 Dec 2008 Posts: 87 Location: US
|
|
|
|
@dbz: that's the entire code read one after the another. there is no additional stuff. i had written this "gobblety-gook" to test the behavior of OCCURS DEPENDING ON. It's better to explain it step by step rather than trying to attach the entire (doesn't make sense in this case, since it's the entire code shown here)
and about the SSRANGE option been turned off, I do understand. However there is a catch when it comes to overwriting the subsequent working storage.... It doesn't if the subsequent working storage starts under a new level... see below -
Declaration (the one that would get overwritten):
Code: |
01 WS-ARRAY-1.
05 WS-ARR0 OCCURS 1 TO 10 TIMES DEPENDING ON WS-H
INDEXED BY WS-0.
10 WS-ARR00 PIC X(1).
05 WS-TEMP-1.
10 WS-TEMP-2 PIC X(1).
10 WS-TEMP-3.
15 WS-TEMP-4 PIC X(1). |
Declaration (the one the would not get overwritten):
Code: |
01 WS-ARRAY-1.
05 WS-ARR0 OCCURS 1 TO 10 TIMES DEPENDING ON WS-H
INDEXED BY WS-0.
10 WS-ARR00 PIC X(1).
01 WS-TEMP-1.
05 WS-TEMP-2 PIC X(1).
05 WS-TEMP-3.
10 WS-TEMP-4 PIC X(1).
|
In the latter, a new level was started and believe me (I have tested it), it will not go over to the subsequent working storage.
@robert: the real difference comes into picture when you split the data into chunks using LENGTH OF. This helps a lot in cases where you have variable amount of data involved. One example to explain the case (which was used in splitting and transmitting data as segments to MQ) -
var_block <-- some block that contains variable data driven by another DEPENDING ON variable... say i
now LENGTH OF used on var_block with i = 10 and i = 20 will give different lengths.
len = LENGTH OF var_block
Assuming length of one segment = 32K = seg_max_len
divide len by seg_max_len giving msg_segs remainder
if remainder > 0
add +1 to msg_segs
And it's been a treat to watch the code perform so well... I had a structure that would take around 43 segments in case of a structure without DEPENDING ON and what shall I say, it reduced to 1 - 2 segments with OCCURS DEPENDING ON. I agree that the allocation is done with the maximum, but if you couple that with the above logic, it does real good.
I will definitely look into the SSRANGE part (somehow that missed mind
@Bill: Been consulting the manuals always and will do that again. Will check with friends, check online, do whatever it takes...
about the preserving data part, I found a workaround by introducing a new level for the subsequent variables (like mentioned above).
Just wanted to know how this allocation gets done.
Thanks all for your time... Waiting for more coders to take a peek
Regards,
C.T. |
|
Back to top |
|
|
dick scherrer
Moderator Emeritus
Joined: 23 Nov 2006 Posts: 19243 Location: Inside the Matrix
|
|
|
|
Hello,
Suggest you look at the addresses/displacements of the data that is shown by the compile. |
|
Back to top |
|
|
cybertaurean
New User
Joined: 22 Dec 2008 Posts: 87 Location: US
|
|
|
|
@dick: sure... let me try that! thanks!!! |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8700 Location: Dubuque, Iowa, USA
|
|
|
|
Quote: |
However there is a catch when it comes to overwriting the subsequent working storage.... It doesn't if the subsequent working storage starts under a new level. |
This merely means you have a LOT of reading ahead of you -- start with page 1 of the COBOL Language Refernce manual and continue through the appendices; then start with page 1 of the COBOL Programming Guide manual and continue through the appendices. Both manuals can be found via the Manuals link at the top of this page. To show you just how wrong you are, here's the code:
Code: |
77 WS-H PIC S9(02) VALUE 10.
01 WS-ARRAY-1.
05 WS-ARR0 OCCURS 1 TO 10 TIMES
DEPENDING ON WS-H
INDEXED BY WS-0.
10 WS-ARR00 PIC X(1).
01 WS-TEMP-1.
05 WS-TEMP-2 PIC X(1) VALUE 'Y'.
05 WS-TEMP-3.
10 WS-TEMP-4 PIC X(1) VALUE 'Z'.
01 WS-END PIC X(08) VALUE 'END'.
PROCEDURE DIVISION .
PARA-1.
DISPLAY 'INITIAL'.
DISPLAY 'WS-H >' WS-H '<'.
DISPLAY 'WS-ARRAY-1 >' WS-ARRAY-1 '<'.
DISPLAY 'WS-TEMP-1 >' WS-TEMP-1 '<'.
DISPLAY 'WS-END >' WS-END '<'.
PERFORM
VARYING WS-0 FROM 1 BY 1
UNTIL WS-0 > 23
MOVE 'A' TO WS-ARR00 (WS-0)
END-PERFORM.
DISPLAY 'AFTER MOVES'.
DISPLAY 'WS-H >' WS-H '<'.
DISPLAY 'WS-ARRAY-1 >' WS-ARRAY-1 '<'.
DISPLAY 'WS-TEMP-1 >' WS-TEMP-1 '<'.
DISPLAY 'WS-END >' WS-END '<'. |
which produces output of
Code: |
INITIAL
WS-H >1{<
WS-ARRAY-1 >..........<
WS-TEMP-1 >YZ<
WS-END >END <
AFTER MOVES
WS-H >1{<
WS-ARRAY-1 >AAAAAAAAAA<
WS-TEMP-1 >AA<
WS-END >END < |
When you can explain why your code does not overlay WS-TEMP-1 and my code does, you will have learned something. |
|
Back to top |
|
|
dbzTHEdinosauer
Global Moderator
Joined: 20 Oct 2006 Posts: 6966 Location: porcelain throne
|
|
|
|
i will only bother to say,
learn about memory allocation for level-01 vs level-02 thru level-49.
learn that and you will not be tempted make yet another post
which shows your lack of knowledge.
and stop trying to learn basics thru observation.
fundamentals need to be learned by understanding everything.
observing causes you to make to assumptions. |
|
Back to top |
|
|
cybertaurean
New User
Joined: 22 Dec 2008 Posts: 87 Location: US
|
|
|
|
@robert: In your example, why didn't the remaining 13 bytes not overwrite WS-END?
@dbz: tried searching for memory allocation for level-01 v/s level-02 thru level-49. Any links? |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8700 Location: Dubuque, Iowa, USA
|
|
|
|
From section 5.3.16 of the COBOL Language Reference manual, available via the Manuals link at the top of THIS page:
Quote: |
In the file section, the compiler assumes that all level-01 records that contain SYNCHRONIZED items are aligned on doubleword boundaries in the buffer. You must provide the necessary slack bytes between records to ensure alignment when there are multiple records in a block.
In the working-storage section, the compiler aligns all level-01 entries on a doubleword boundary.
For the purposes of aligning binary items in the linkage section, all level-01 items are assumed to begin on doubleword boundaries. Therefore, if you issue a CALL statement, such operands of any USING phrase within it must be aligned correspondingly. |
Since WS-ARRAY-1 starts on a doubleword boundary, and it is 10 bytes long, there are 6 slack bytes between the last byte of WS-ARRAY-1 and the first byte of WS-TEMP-1 -- which must begin on a doubleword boundary since it is a level 01 variable. Since WS-TEMP-1 is 2 bytes long, there are also 6 slack bytes between the last byte of WS-TEMP-1 and the first byte of WS-END. 10 bytes plus 6 slack bytes plus 2 bytes plus 6 slack bytes is 24 bytes -- hence the memory overlay stops before the beginning of WS-END and it is not affected. This is what I meant when I said you need to learn something -- the same thing Dick has said. If my loop had run to 500 or 5000 instead of 23, I probably would have gotten a sytem abend -- S0C1 or S0C4 most likely -- once the overlay started wiping out program instructions. |
|
Back to top |
|
|
dick scherrer
Moderator Emeritus
Joined: 23 Nov 2006 Posts: 19243 Location: Inside the Matrix
|
|
|
|
Hello,
Quote: |
@robert: In your example, why didn't the remaining 13 bytes not overwrite WS-END? |
To learn about this was your "assignment". . .
Quote: |
@dbz: tried searching for memory allocation for level-01 v/s level-02 thru level-49. Any links? |
This (and very much more) is in the documentation.
Surely, you cannot have actually read these so quickly. . . |
|
Back to top |
|
|
cybertaurean
New User
Joined: 22 Dec 2008 Posts: 87 Location: US
|
|
|
|
@robert and dick: thanks so much! let me dig in to this section... |
|
Back to top |
|
|
dbzTHEdinosauer
Global Moderator
Joined: 20 Oct 2006 Posts: 6966 Location: porcelain throne
|
|
|
|
cybertaurean wrote: |
@robert and dick: thanks so much! let me dig in to this section... |
guess he told me. |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8700 Location: Dubuque, Iowa, USA
|
|
|
|
Dick I guess 30-odd years of COBOL experience don't count for much these days, does it? |
|
Back to top |
|
|
dbzTHEdinosauer
Global Moderator
Joined: 20 Oct 2006 Posts: 6966 Location: porcelain throne
|
|
|
|
not when the info is delivered sans all the sugar and honey coating the pc (politically correct) generation expects.
(which obviously tends to motivate me to add more lemon the next time.) |
|
Back to top |
|
|
cybertaurean
New User
Joined: 22 Dec 2008 Posts: 87 Location: US
|
|
|
|
@dbz: lol... I thanked you too... You have any reason to think you wouldn't be thanked ;)
@robert: only change is constant ... and 30 years of COBOL!!! WOW!!! |
|
Back to top |
|
|
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
dbzTHEdinosauer wrote: |
[...]
and stop trying to learn basics thru observation.
fundamentals need to be learned by understanding everything.
observing causes you to make to assumptions. |
Cybertaurean,
You have to really take this to heart. Take time to understand how the assumption you made was wrong, and how all the time you were observing the wrong thing.
You started off setting your ODO number to 6. Then you moved "1" and "2" to your fields following the ODO. You displayed the "array" and the two fields. You then tried with 7 for the ODO number, and started to "loose" the data. Yet all the time, the 1 and the 2 are staring at you from the screen, in the display of array.
The only thing that changes for those following fields is the start position of those following fields. The data stays slap-bang where you put it originally. That is why you "see" it again when you set the length of the ODO back to 6.
You "assumed" that when you displayed the other fields, they should show you the value. They didn't, so you "assumed" the data was somehow lost. If you cut the assumptions, complete the observation (there's the damn stuff, why's that) and consult the manual, you get the answers.
To preserve the value of the 1 and 2, you have to
Code: |
Save values of all fields which are part of the same 01 and which follow (ie are not subordinate to) the ODO.
Change the value of the ODO number.
Replace the values of the fields you saved. |
If you add that logic to your code, you will retain the "1" and "2" values where you think they should be and not just leave then where you last put them.
I didn't know LENGTH OF would give different values for an ODO group. Why not? Because I already know the length, it is the ODO number multiplied by the length of the field which is occurring. In plaace of already knowing the length, you have put LENGTH OF through some excrutiating stuff to get what you already know.
Again you missed the "obvious". This time it worked anyway. But you then use the assumption you have made about this to somehow support what you have been saying about your new discovery.
There happen to have been a number of discussions ODO. In this forum. It is worth your while to locate them and understand them. Everything you have done above is covered, even with the ODO length as zero, your remaining question from above. Try to get to the stage where you can explain it to us.
If you want to "see" the slack bytes, look at the DMAP (notice the offsets), look at a dump, or use the Junk Buster. |
|
Back to top |
|
|
cybertaurean
New User
Joined: 22 Dec 2008 Posts: 87 Location: US
|
|
|
|
That's a lot of information, Bill. And I'm really * x (Lim x-> inf.) grateful for that. Gotta learn a lot from the Manual.
PS: I guess they have Redbook versions for the manual, r8? Let me check . Thanks again!!! |
|
Back to top |
|
|
dick scherrer
Moderator Emeritus
Joined: 23 Nov 2006 Posts: 19243 Location: Inside the Matrix
|
|
|
|
Hello,
At the top of the page is a link to "IBM Manuals. At the top of the list are COBOL manuals. Use the Language Reference and Programming Guide for your release of the compiler.
Suggest you bookmark or download the manuals that you will use regularly. |
|
Back to top |
|
|
dbzTHEdinosauer
Global Moderator
Joined: 20 Oct 2006 Posts: 6966 Location: porcelain throne
|
|
|
|
cybertaurean wrote: |
PS: I guess they have Redbook versions for the manual, r8? Let me check . Thanks again!!! |
Redbooks are supplementary information,
they are not 'dummies' versions of manuals.
as memory mapping for COBOL and COBOL statement definition and explanation are rather basic,
and the Application Programmer's Guide and the Language Reference discuss these topics in detail,
other than migration issues,
you will not find a Redbook about these topics. |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8700 Location: Dubuque, Iowa, USA
|
|
|
|
Quote: |
I guess they have Redbook versions for the manual, r8? |
Redbooks are more how-to manuals -- they never replace the basic manuals. You may find memory allocation information in some Redbooks, but you won't find any Redbooks just talking about COBOL for example. |
|
Back to top |
|
|
|