プロが教えるわが家の防犯対策術!

fortranでプログラムをつくりました。
コンパイルは成功しているのですが、プログラムが途中で止まってしまいます。
そして「segmentation fault」とエラーが出ます。
このエラーは何を意味しているのでしょうか?

A 回答 (5件)

segmentation faoultはメモリ参照ミスによるエラーです。



拡張無しのfortranの場合、一般的に
・配列の添え字の設定ミス
・ファイル入出力時の変数設定ミス
・共有common初期化にcommon配列を利用した時の次元数、要素数が合っていない
・計算型gotoや算術if文で飛び先行番号の数が足りない
・etc...

ポインタ型の拡張がある場合
・ポインタ変数の値が不正

まとめると「アプリケーションのワーク領域、プログラム領域以外のメモリ領域に対する参照」が発生した場合にsegmentation faultとなります。
これは、データ参照時にプログラム領域への参照が発生した場合に起こる処理系もあります。

極端な話、32ビットアドレスでinterger*4の配列の添え字に10億を与えると確実にsegmentation faultが発生します。

プログラムの内容、動作環境が不明なのでこれくらいしかわかりません。

この回答への補足

回答ありがとうございます。
 しかしあまり詳しくないので僕にかいてあることがちょっとよくわかりません。

 動作環境は
 IBMのRS6000のバッチシステムを利用しています。
 プログラムの内容は
 研究で使うデータの並べ替えです。
 どの部分でとまっているのかわかりましたが、その命令のどこが間違っているかわかりません。配列の添え字、dimensionも問題ありません。

 とりあえず、今自分でわかる情報はこれくらいです。

補足日時:2001/03/23 16:50
    • good
    • 0
この回答へのお礼

すいません、補足のところにお礼を書いてしましました。

お礼日時:2001/03/23 17:15

下で専門家の方が的確な答えを出されているので、補足だけ。



現象よりも

1.何故そうなったか?
2.どこでそうなったか?
3.どうしたらいいか?

知った上で正常に動かしたいのでしょ?

1.は専門家も書かれているとおりです。

2.はバッチでもコンパイル時のオプション次第で、デバッガ相当のものを動かし、どういうサブルーチン(または関数)の呼び順でエラーになったか分かるはずです。しかし、メモリ-を破壊しよぼど変な落ち方をしている場合は、それも分からない場合があります。

3.2.でどこでエラーになっているか分かったらそこを修正します。場合によっては、落ちているのはその場所でも、別のところで悪さをした結果、巡り巡ってそこで落ちていることもあります。

メモリーの参照をミスっても「segmentation fault」になるとは限りません。つまり「他人の家」を壊すと怒られるし、壊せないようになっていますが、「自分の家」なら壊しても怒られないのです。「自分の家」でも命令部は壊れないようにする処理系もあったと思います。「他人の家」は壊すだけでなく、見ることも禁止されています。

能書きは兎も角、もし上の方法で分からないなら、ソースコードを丹念に見直してください。ごくまれにコンパイラやランタイムライブラリのバグである場合もありますが、99.9%間違いなくあなたのプログラムの間違いが原因です。
    • good
    • 0
この回答へのお礼

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

 コンパイラはIBM版AIX用fortranコンパイラを使ってます。デバッガ相当のオプションは今調べています。

 止まってい部分はどうやらこの命令のようです。

do 35 j=1,512
do 35 i=5,512
nvr((i-4),sp(j))=elepr(i,j)
35 continue

 配列の大きさ、整数、実数は大丈夫です。
 この部分で止まっているようですが、この命令の前後で不具合があるのでしょうか?
 プログラムの見直しは何度もしています。

お礼日時:2001/03/24 17:12

プログラムを途中で切ってdatファイルに計算結果を書き出して、


期待した結果どおりに数値計算されているか確かめてみるのも
いいかも知れません。
(1)問題となっているdo文の前まででプログラムを切って
elepr(i,j)の値が正しいかwrite文で書き出してみる。
(2)問題となっているdo文自体を変えてちゃんと回っているか確かめる。
open(unit=2,file='test.dat',form='formatted')
do j=1,512
do i=5,512
nvr((i-4),sp(j))=elepr(i,j)
write(2,*)i,j,nvr((i-4),sp(j)),"/n"
end do
end do
close(unit=2)
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
 いろいろwrite文で書き出してみましたところ、do文でデータを読み込む際に指定した数だけデータを読み込んでいないことがわかりました。
 しかし、なぜこのようになるかわかりません。
 メモリーなどが関係しているのでしょうか?
 何かわかることがあったら教えてください。

お礼日時:2001/03/29 22:17

どうなんでしょう?たぶんプログラム文のミスだと思うのですが。


約500×500くらいの情報量なら、g77(Debian:Linux)の駄目コンパイラーでもうちの駄目PCで一日くらいかければ計算できますが。。
(1)spはintegerになっているか確かめる。
(2)何行何列までは計算値がでているか見てみる。
(3)配列宣言で、nvr(1:508,[ここはspの整数値]),elepr(1:512,1:512)
としておくと変数のなかの行列は指定された整数値が使えます。
(4)nvr(1,sp(1))=elepr(1,5)という計算がなされているがそれは
自分のしたい計算なのかどうか?elepr(1,1)などは計算に関係しないが
それは自分がやりたいことと合っているのかどうか?
(5)計算のかかる部分はsublutineにした方が計算速度はあがる
(6)実数変数の中の整数値は6.かfloat(6)などにしていないと計算が飛ぶ可能性がある

ということを試してみてどうでしょうか?回りませんか?
eleprの値はちゃんと出ているんですよね?

この回答への補足

dimensionのサイズを倍にしてみたら計算が動きだしました。
今までぎりぎりでやっていたのですが・・・・

dimensionに余裕を持たせないとfortranはダメなものなんでしょか?

補足日時:2001/03/30 21:36
    • good
    • 0
この回答へのお礼

再び回答ありがとうございます。
(1)は確認してOKです
(4)は自分のやりたい計算です
(6)は直しましたが駄目です

(2)より
 read文で1024個データを読み込む部分が599個しか読み込んでいません。ほかでのreadでは26万個近く読み込むはずが18万個程度のデータしか読み込んでいない状況というのがわかりました。
 何かわかることありますか?

お礼日時:2001/03/30 19:39

dimensionに余裕を持たせないとfortranはダメなんてことはないですよ。

suppercomputerで計算させるときのプログラムはfortranなので。逆にプログラムのどこかで、指定の配列をオーバーして計算をさせていたということは考えられます。
    • good
    • 0

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