みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

回答受付中の質問

汎用機COBOLのメモリ管理について

汎用機COBOLのオンラインPGですが、明細データをDBから読み込んで、配列に入れていますが、99%は300件以下です。1%は300件以上ですが、その場合1000件以上になります。そこで、通常は300の配列で処理をし、300件を超えたら1100の配列で処理をする様にして、メモリの使用を抑えようとしています。この場合、可変長配列を使用すれば、何の問題も無いのですが、自分が配属された時には、2つの固定長配列のCOPY句を使用して、目的を達成しようとしていました。方法は、
(1)配列300のCOPY句をワークエリアに、配列1100のCOPY句をリンケージエリアに配置する。リンケージエリアにCOPY句を配置する理由は、何もしなければ、メモリを消費しないからです。
(2)配列300のワークエリアを初期化して、そのアドレスをリンケージエリアの配列1100にセットする。この時点では、ワークエリアとリンケージエリアで配列300分のメモリアドレスを共有する。
(3)共通サブルーチンに(2)のアドレスを渡し、明細を取り込む。1100を超えた場合は、アドレスを取り直して、返却する。
(4)メインPG側で、返却されたアドレスをリンケージエリアの配列1100のエリアにセットし直す。
(5)判定や計算をする場合は、リンケージエリアの配列1100の項目名を使用する。
以上が、大まかな処理の流れです。
そこで、疑問なのが明細が300件未満の場合です。使用しているメモリの場所は、ワークエリアの配列300とリンケージエリアの配列1100とは、同じワークエリアのメモリアドレスになるので、どちらのCOPY句で処理しても、同じ結果になります。この時、配列300分のメモリしか使用していない事になっていますが、判定や計算には配列1100の項目名を使用しています。そこで疑問なのは、アドレスセットだけなら問題無いにしても、配列1100の項目を処理に使用した時点で、配列1100分のメモリが確保されてしまうのではないかという事です。つまり、節約しているつもりが、配列1400分のメモリを浪費しているのではないかという疑問です。配列300の場合と配列1100の場合とで、PGを完全に二重化すれば問題は無いとおもいますが、メーカーの担当エンジニアは問題無いと言っているのですが、誤解が有るような気がしてなりません。どなたか、解る方がいらっしゃいましたら、ご教示頂けると幸いです。どうぞよろしくお願い致します。

投稿日時 - 2019-08-14 22:17:25

QNo.9645729

すぐに回答ほしいです

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(7)

ANo.7

>SET ADDRESS OF ~

いや、そういう事じゃなくて、
問題の個所のアドレスを「直接 確認したら」どうなるのかなと思って。

http://ibmmainframes.com/about64078.html

投稿日時 - 2019-08-18 09:03:27

補足

問合せ、ありがとうございます。
SET ADDRESS で、ワークエリアにアドレスを保存したものを、DISPLAYで確認しようとしましたが、何をやっても同じ文字列が表示されて、変化を確認できません。別の配列のアドレスをDISPLAYすると、配列の中身が表示されたりしますが、問題となっている配列では、意味の解らない文字列が表示されるだけです。文字列の長さは30~40文字程度だったと思います。アドレスの確認方法がお解りでしたらご教示頂けると幸いです。

投稿日時 - 2019-08-18 10:33:47

ANo.6

お使いのCOBOLでは、
ADDRESS OF 項目名
は、使えないのですか?

投稿日時 - 2019-08-17 13:16:32

補足

SET ADDRESS OF ~ なら、質問内容の(2)で使用しています。今問題になっているのは、ワークエリアの配列300のアドレスをリンケージエリアの配列1100に設定した場合、固定長配列1100の項目名を使用した時に、301番目以降の領域にメモリが割り当てられるのか否かという事です。PGでは、読込んだDBの件数が少ない場合、リンケージエリアの配列には、配列300分のメモリしか割り当てていませんが、リンケージエリアの配列1100は、あくまでも固定長なのですが、その300番目以内の項目(配列1100の項目名)を判定や計算で参照した場合に、配列301番目以降のメモリが、固定長ゆえに割り当てられてしまうのか、それとも可変長的に配列300のままなのかを確認したいと思っております。宜しくお願い致します。

投稿日時 - 2019-08-17 23:27:03

ANo.5

メインのリンケージエリアは実メモリーではありません。
サブプログラムにあるデータエリアを指しています。

>300件以内の場合で~
300件以内の場合はサブを呼びませんからサブの1100のメモリーは
ありません。
1100番目の項目はプログラム内か、はたまた別のプログラム内かの
アドレスを指しています。

>記憶保護例外等の異常終了はしません
これはコンパイラーやOSが判定していなければ起こりえません。
0番目であってもアクセスはできます。
読み込みに問題は出ません。
書き換えてみてください。どこかがおかしくなりますからw。(超危険)

投稿日時 - 2019-08-16 15:13:05

補足

度々の回答、ありがとうございます。
通常、リンケージエリアはサブPG側に設定されると思いますが、今回の場合、親PG側にリンケージエリアが設定されていますので、サブPGは無関係なのではないかと思います。オンラインPGなので、オンラインPG間でデータの受渡をするSPAの領域がリンクの相手先と考えられます。アドレスを設定しない状態で、いきなりデータの転送をしても何の問題も起きていません。普通に書込みと読出しができています。なので、書込みをした時点で、おそらくSPAにメモリが取られているのではないかと思いますが、IF文とか計算処理による参照のみとかの場合は、ちょっと判りませんが、そこの所の確認ができればと思っています。

投稿日時 - 2019-08-17 00:37:22

ANo.4

> ただし、全く割り当てられていないのであれば、使用した時点で記憶保護例外等で異常終了しそうな気がしますが、いろいろ実験した結果、そうはなりません。したがって、使った時点でメモリが割り当てられるのではないかと推測しています。

全然違います。
LINKAGE SECTION以外で、メモリを確保して、そのメモリの中を区切ってアクセスするためにLINKAGE SECTIONの定義を使います。

プログラムのどこかで、データ量に合わせて適切なサイズのメモリを確保しているはずです。探しましょう。

投稿日時 - 2019-08-15 22:44:36

補足

回答、ありがとうございます。
リンケージエリアについてですが、実験でリンケージエリア内にPG内で使用していない適当なcopy句を設定して、初期処理でいきなりIF文で項目判定したりDISPLAYしたり、固定値をMOVEしたりしましたが、普通のワークエリアと同じように使用できました。PG内の他のところでエリアを定義しているという事はありません。今回の場合、最初の配列300については、ワークエリアのアドレスを設定していますが、残りの配列800についてはアドレス未設定です。しかし、中身はともかくとして、普通に使えるので、メモリが取られてしまってるんじゃないかと思っています。現状は、メモリが取られていない事を前提に仕事をしていますが、無駄な事の為に苦労させられている様な気がして仕方がありません。

投稿日時 - 2019-08-16 02:39:52

ANo.3

linkage sectionについては、他の回答があるのでそこは覗いて、そもそもCOBOLはdata divisionの01レベルを定義毎に4kずつメモリを確保していったと思います。(最近のマシンでは8kかもしれない)なので、その中で、300個分のエリア(occues句)とか1100個分取ろうが、関係なかったと思います(これを超えるとコンパイルでセグメントエラーとなるなので、01レベルの項目をもう一つ設けそのなかでデータ定義を行う。むしろ1100個取ったとき何byteあるのかが重要)。また、何故そんなにメモリ確保しなければならないのでしょうか?メモリーソートを目的なのでしょうか?それとも、ランダムアクセスをメモリ上で行いたいのでしょうか?COBOLも、77時代はOCCURSで指定できる個数は
255までしかできませんでした。85時代で65534まで拡張されました(ちょっとうる覚え)。それでも、jsとかjclであらかじめソートするとか、或いは、ランダム編成、索引順編成、相対編成を利用してpgであまりメモリソートしないように工夫してました。最近ではRDBの利用も一般的になってきたと思います。また、汎用機はマルチタスクの区切りとして、ファイルIOを起点としていると思います。仮にPGで多くのテーブル操作をすると
そのPGがCPUを離さずになり他のPGが動かなくなり、他の人に迷惑がかかるかと思います。また、汎用機のメモリはほとんとPCのメモリ量と変わりません。
4Gとかそんなもんです。そのなかで、汎用機特有のバッファプールとか定義し複数のOSなどが稼働し、残った領域にpgを動かす領域を確保しているかと思います。なので、多くのメモリを利用するとシステム自体がのっからなくなる可能性もあります。それらを考慮して構築しては如何でしょうか?

投稿日時 - 2019-08-15 19:36:44

補足

回答ありがとうございます。
普通のシステムとは異なり、1万シリンダを超えるファイルが、無数に存在し、データ件数も何百万件はザラです。配列サイズも50k程度でも問題無いですし、そんなPGが既に何百本と動いています。とは言え、リソースも無限ではない為、メモリの節約とか同じRDBを何回もアクセスしない等に気を遣って設計しています。

投稿日時 - 2019-08-15 21:45:53

ANo.2

リンケージエリアの意味が理解できていませんね。
リンケージエリアは、実際のメモリは確保しません。別途確保されたメモリをアクセスするための定義だけです。

投稿日時 - 2019-08-14 23:06:29

補足

回答ありがとうございます。
リンケージエリアがメモリを確保しないのは、理解しています。不必要なメモリを使わない為に、意図的にリンケージエリアを使用しています。ただし、全く割り当てられていないのであれば、使用した時点で記憶保護例外等で異常終了しそうな気がしますが、いろいろ実験した結果、そうはなりません。したがって、使った時点でメモリが割り当てられるのではないかと推測しています。だとすると、300件以下なので300迄のメモリを使用しているつもりが、配列1100の項目名を使用している為、300迄はアドレスが共通なので、残りの800分のメモリが確保されてしまうのではないかと疑っています。最初の質問では、300+1100=1400と思っていましたが、実際は最初の配列の300はアドレスが同じなので、300+(1100ー300)=1100が正しいのではないかと思います。結局、配列1100のCOPY句で一本化しても同じなのではないかという疑問です。COPY句を二つ使っている事による障害が起きているので、なんだかな~という感じです。

投稿日時 - 2019-08-15 22:06:54

ANo.1

>配列1100分のメモリが確保されてしまうのではないか
その心配はありません。1100の配列をメモリーにとっているのは
サブルーチンの方だからです。呼ばなければメモリーは食いません。
300取る→超える→サブルーチンで1100取る→超える→サブルーチンで
1100取る。。。となります。
ワークの方の名前でもリンクの方の名前でも開始アドレスが同じなら問題無し。

昔は可変長配列はなかった。(私も知らなかった)
配列を最大件数とれば動くがそれではメモリーがもったいない。
苦肉の策としてこうなったのです。

私の先輩が作ったプログラム。
住所の同じ(つまり1軒)ものを配列に入れて処理していた。
当初は家族分だからと高をくくり20にしていた。
そしたら件数がオーバーしてデータをよく見たら「〇〇ホーム」になってた。
つまり老人ホームで全員がまとめて送っていたというオチ。
ま、一瞬で終わるプログラムだし、件数増やしていましたが。

投稿日時 - 2019-08-14 23:05:53

補足

回答ありがとうございます。
リンケージエリアですが、オンラインのメインPG側にリンケージエリアが有りまして、サブルーチンのリンケージエリアは、それはそれで別に存在しています。問題なのは、メイン側のリンケージエリアに配列1100のCOPY句を設定しているのが厄介なところで、サブルーチン側で配列300のメモリ使用のままで返したとしても、メイン側で配列1100のCOPY句を使用した時のメモリの振舞が判らないので、困っています。ちなみに、300件以内の場合で、1100番目の項目をIF文で空白判定し1100番目の項目をDISPLAYをしても、記憶保護例外等の異常終了はしませんので、メモリは取られている様な気はするのですが、そこの所がハッキリしません。

投稿日時 - 2019-08-16 00:58:57

あなたにオススメの質問