電子書籍の厳選無料作品が豊富!

他人が作ったFortran(恐らくFortran77)のプログラムで計算をしようとしています。
コンパイルはできるのですが,実行するとエラーが出てしまい困っています。

エラーメッセージは
「forrtl:severe(157):Program Exception - access violation」
となっていて,実行時エラー番号で調べると
「プログラムが適切な参照権を持っていない仮想アドレスに書き込み,または読み取り
を行おうとした」と出ていました。

Fortran初心者の自分にはイマイチ意味が判らないのですが,エラーが出た後に
サブルーチンのある決まった場所に黄色い矢印が示されます。
そこで今,その部分のサブルーチンを確認しているところです。

前置きが長くなってしまいましたが
サブルーチンの中を確認している途中で疑問に思った所が一つあります。
問題のサブルーチンは
---------------------------------------
call dbesl(EN,0,BX0,BY0,BI0,BK0)
 
 
subroutine dbesl(X,NOR,BX,BY,BI,BK)
FN = NOR
 ・
 ・
 ・
11 NOR = FN               <---この行に黄色い矢印が出る
return
end
---------------------------------------
となっているのですが,サブルーチンを呼び出すcall文の所で
2つ目の引数が『0』となっているのは正しい使い方なのでしょうか?

どうもサブルーチン内の計算をしてメインプログラムに引数を返す所が
おかしいような気がしています。
因みにメインプログラムに戻る際の"FN"の値は『0』となっていました。

コンパイラはCompaq Visual Fortranを使用しています。
足りない情報は出来るだけ追記していきますので,ご教示宜しくお願いします。

A 回答 (2件)

FORTRANはCのように値呼び出し(Call by Value)ではなく、すべての変数はアドレス呼び出し(Call by Reference)になります。

ですから、このサブルーチン呼び出しでは、0の格納されている番地をサブルーチンに渡し、その番地にデータFNを格納して返していることになります。これが行われると、プログラムの他のところで使われている定数としての0がすべて置き換わってしまいますから、通常、こういった使い方は許されないようになっています。

コンパイラは、ここでの0など、定数として定義された値は、リテラルプールという特別な場所に格納します。x86系のコンパイラだと、DS(データセグメント)ではなく、CS(コードセグメント)に配置する場合もあるかもしれません。
実際には、メモリー上では、0という値をもった変数でしかありません。ただ、プログラムの他の場所で0が使われる場合にもこのリテラルプールの0を参照するようになっています。ですから、この0の所にカキコみれてしまうと、プログラム中で0を引用しているところがすべておかしくなってしまうのです。

昔のFORTRANには、このあたりの保護がいい加減で、リテラルが書き換わってもそのまま実行してしまうものもありましたが、最近はちゃんと管理していると思います。

まあ、単純には0を変数にしてそこに0を代入して呼び出せば(名前からするとBessel関数かな)いいとは思いますが、元々がデータ型に無頓着なコーディングしているようだし、他にもエラーがありそうだなあ。
    • good
    • 0

>2つ目の引数が『0』となっているのは正しい使い方なのでしょうか?



細かい理由の説明は省きますが、十中八九それが原因でしょう。

コンパイラによってはこれを許すものもあるかもしれませんが、
たぶん「場合によっては使えるものもある」程度であって
「どのコンパイラでも使える」というものではないと思います。

とりあえず、適当な変数を呼び出し元に追加して、それに0を入れた上で
subroutine dbesl(X,NOR,BX,BY,BI,BK) を呼び出してはどうでしょうか。
    • good
    • 0
この回答へのお礼

回答ありがとうございました。

ご指摘の部分を修正したところ,無事計算できました。
また何かありましたら宜しくお願いします。

お礼日時:2008/10/03 16:04

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!