MVCL命令でデータの移動先アドレスや移動するデータの長さを間違えた場合、データの移動中にプログラム割り込みを起こしS0C4でABENDすることがあります。命令で指定したレジスターは、ABENDした時点の移動元や移動先のアドレス、残りの領域長やデータ長を示します。
1 2 3 4 5 6 7 8 9 10 11 12 |
----+----1----+----2----+----3----+----4----+----5----+----6----+----7-- : GETMAIN RU,LV=4000,LOC=BELOW LR R2,R1 LR R0,R1 L R1,=F'4096' LA R14,DATA LR R15,R1 MVCL R0,R14 MOVE DATA TO OBTAINED STORAGE : DATA DC 120CL36'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' : |
この命令は、GR14が示すアドレスの領域内データをGR0が示すアドレスの領域にコピーするものです。領域の長さは対となっているGR1およびGR15に入っています。この命令実行中に次に示すようなPSWとレジスターでABENDしました。
1 2 3 4 5 6 7 8 9 |
DATA AT PSW 00007F08 - 41E0C03C 18F10E0E 00000ACA GR 0: 0000A000 1: 00000060 2: 00009060 3: 009D29D4 4: 009D29B0 5: 009EC818 6: 009C1FE0 7: FD000000 8: 009EC9E0 9: 009ECAD8 A: 00000000 B: 009EC818 C: 80007EE0 D: 00006F40 E: 00008EBC F: 00000060 |
ABENDした時点のGR0はx0000A000、GR14はx00008EBCで残りデータ長はx60バイトを示しています。SYSUDUMPに出力された移動元と移動先の領域内容は次の通りでした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
GR14=x00008EBC(移動元) ======================= 00008E00 F6F7F8F9C1C2C3C4C5C6C7C8C9D1D2D3 D4D5D6D7D8D9E2E3E4E5E6E7E8E9F0F1 00008E20 F2F3F4F5F6F7F8F9C1C2C3C4C5C6C7C8 C9D1D2D3D4D5D6D7D8D9E2E3E4E5E6E7 00008E40 E8E9F0F1F2F3F4F5F6F7F8F9C1C2C3C4 C5C6C7C8C9D1D2D3D4D5D6D7D8D9E2E3 00008E60 E4E5E6E7E8E9F0F1F2F3F4F5F6F7F8F9 C1C2C3C4C5C6C7C8C9D1D2D3D4D5D6D7 00008E80 D8D9E2E3E4E5E6E7E8E9F0F1F2F3F4F5 F6F7F8F9C1C2C3C4C5C6C7C8C9D1D2D3 00008EA0 D4D5D6D7D8D9E2E3E4E5E6E7E8E9F0F1 F2F3F4F5F6F7F8F9C1C2C3C4C5C6C7C8 00008EC0 C9D1D2D3D4D5D6D7D8D9E2E3E4E5E6E7 E8E9F0F1F2F3F4F5F6F7F8F9C1C2C3C4 00008EE0 C5C6C7C8C9D1D2D3D4D5D6D7D8D9E2E3 E4E5E6E7E8E9F0F1F2F3F4F5F6F7F8F9 00008F00 C1C2C3C4C5C6C7C8C9D1D2D3D4D5D6D7 D8D9E2E3E4E5E6E7E8E9F0F1F2F3F4F5 00008F20 F6F7F8F9C1C2C3C4C5C6C7C8C9D1D2D3 D4D5D6D7D8D9E2E3E4E5E6E7E8E9F0F1 00008F40 F2F3F4F5F6F7F8F9C1C2C3C4C5C6C7C8 C9D1D2D3D4D5D6D7D8D9E2E3E4E5E6E7 00008F60 E8E9F0F1F2F3F4F5F6F7F8F9C1C2C3C4 C5C6C7C8C9D1D2D3D4D5D6D7D8D9E2E3 00008F80 E4E5E6E7E8E9F0F1F2F3F4F5F6F7F8F9 C1C2C3C4C5C6C7C8C9D1D2D3D4D5D6D7 00008FA0 D8D9E2E3E4E5E6E7E8E9F0F1F2F3F4F5 F6F7F8F9C1C2C3C4C5C6C7C8C9D1D2D3 00008FC0 D4D5D6D7D8D9E2E3E4E5E6E7E8E9F0F1 F2F3F4F5F6F7F8F9C1C2C3C4C5C6C7C8 00008FE0 C9D1D2D3D4D5D6D7D8D9E2E3E4E5E6E7 E8E9F0F1F2F3F4F5F6F7F8F900000000 GR0=x0000A000(移動先) ====================== 00009F00 C1C2C3C4C5C6C7C8C9D1D2D3D4D5D6D7 D8D9E2E3E4E5E6E7E8E9F0F1F2F3F4F5 00009F20 F6F7F8F9C1C2C3C4C5C6C7C8C9D1D2D3 D4D5D6D7D8D9E2E3E4E5E6E7E8E9F0F1 00009F40 F2F3F4F5F6F7F8F9C1C2C3C4C5C6C7C8 C9D1D2D3D4D5D6D7D8D9E2E3E4E5E6E7 00009F60 E8E9F0F1F2F3F4F5F6F7F8F9C1C2C3C4 C5C6C7C8C9D1D2D3D4D5D6D7D8D9E2E3 00009F80 E4E5E6E7E8E9F0F1F2F3F4F5F6F7F8F9 C1C2C3C4C5C6C7C8C9D1D2D3D4D5D6D7 00009FA0 D8D9E2E3E4E5E6E7E8E9F0F1F2F3F4F5 F6F7F8F9C1C2C3C4C5C6C7C8C9D1D2D3 00009FC0 D4D5D6D7D8D9E2E3E4E5E6E7E8E9F0F1 F2F3F4F5F6F7F8F9C1C2C3C4C5C6C7C8 00009FE0 C9D1D2D3D4D5D6D7D8D9E2E3E4E5E6E7 E8E9F0F1F2F3F4F5F6F7F8F9C1C2C3C4 0000A000 00000000000000000000000000000000 00000000000000000000000000000000 <== |
プログラムではGR14が示す移動元は、自プログラム領域内でアドレスと長さの指定には問題がありません。となれば移動先のアドレスxA000が問題となったものと考えられます。しかし、ダンプ・リストには問題であろうアドレスxA000は有効なストレージ領域として出力されています。仮想アドレスとして存在しているのにどうして不正アドレスでS0C4してしまうのか?という疑問も生じます。
結論から言うと、この場合のxA000は確かに誤ったアドレスなのです。プログラム・コードを見るとGETMAINで長さを4000バイトとして移動先の領域を割り振っているのに、MVCL命令は4096バイトの長さで実行しています。そのため、4000バイト移動し終わった時点でABENDしたものです。
アドレスxA000の領域は存在しないのですからダンプには出てこないはずですが、出てきてしまっているために、それならば有効な仮想記憶域ではないのか?と思ってしまうわけです。
手元にプログラム・コードがあって、単純なミスのようなバグであればダンプがどうであれ、簡単に原因はわかりますが、複雑なプログラムであったり、過去に作られたもので内容もよくわからないといったような場合では、ダンプされた領域の内容から問題を起こしたモジュールや箇所を特定したい場合もあります。プログラムの規模が大きくなると、原因を作った箇所と実際にABENDしたモジュールが違うと言ったことはよくあることです。ダンプ上でxA000は、Storage not availableであるとはっきり出ていればいいのですが、上記のようにダンプにも領域として出てきてしまうと、どうしてこのアドレスでS0C4になるのか?と考えてしまうかも知れません。
実はダンプに出ているxA000からの領域は、このプログラムがABENDした後にMVSのABEND処理によって割り振られた領域です。このケースではSYSUDUMP(あるいはSYSABEND)を出力するための作業域、関連するモジュールのローディングなどに使われていました。ダンプ・リストはABENDした時点の空間内の記憶域を編集して出力しますが、ABENDそのものを処理したりダンプを出力するためにMVSのRTMなど関連するコンポーネントのモジュールが実行されます。そのため、ABEND発生からダンプのためにメモリー内容が読み取られるまでの間にOSの作業域として空間内の領域が使用され、そこがたまたまアプリケーション・プログラムが割り振った領域の直後に続いて割り振られると、ダンプ上では有効な仮想記憶域が続いているように見えるのです。
その後にOSのモジュール名らしきものやABEND処理に使われそうな内容の文字列などが入っていれば当たりもつきますが、ヌル・データなどがある程度続いていたりすると元々GETMAINしていたアプリケーションの領域ではないのか?とも思えてしまうのです。このケースではSYSUDUMPではなくSYSMDUMPでバイナリー・ダンプの出力に変えたところ、xA000の領域はダンプ上存在せず Storage not available となっていました。SYSMDUMPはフォーマットしないのでより少ない作業域で処理されたものと考えられます。
もし、MVCL命令実行中にABENDしたので関連するレジスターからダンプでストレージ内容を確認し、仮想記憶域として出力されているからS0C4するようには見えないが?と思ったら、データの移動元や移動先アドレスがちょうどページの始まりを示すきりのいいアドレス値になっていないかを確認してみて下さい。このケースのようにxA000など仮想ページの開始アドレスつまりページ・バウンダリーになったアドレスであれば、間違いなくデータ移動中に有効なページを超えてデータを処理しようとしたものです。GETMAINしていない領域でも、あるいはFREEMAINしてしまった領域でも、ページの1部でも有効に残っていればそのページの4KBの中であればS0C4にはなりません。そのページを超えて次のページが割り振られていないと、そこでS0C4になります。
いずれにしてもダンプ・リスト(特にSYSUDUMPとSYSABEND)に出てくるメモリー内容は、純粋にアプリケーション・プログラムでだけ使われている領域だけではなく、ABENDした時にはなかったけどABEND処理の過程でリージョン内の領域が割り振られて使われた結果、ダンプに出てくる領域もあるのだということを知った上でダンプを調べると余計な疑問を持たずに済みます。原因がなかなか掴めないと、どうしても他の誰かが悪いのでは?と考えたくなりますが、プログラムがABENDする原因は99.999%自分の作ったプログラムにあるのだと考える方が無難です。