• ベストアンサー

Segmentation Fault (メモリ制限?)

Segmentation Fault (Fortranのプログラム)に関して質問です。 あるデータを処理するプログラムですが、小さなデータの場合問題ないですが、 大きなデータを扱うようになった場合Segmentation Faultとなります。 宣言している配列サイズを超えた部分のアクセスなどでSegmentation Faultが出ることがあるようですが、どうやらそのような現象ではなく、 メモリ制限にひっかかっている感じがいたします。 エラーが出る部分はどうやらSubroutine内の大きなデータ宣言を している部分のようです。(下の例ではtest bが表示れる以前に止まります。) !-------------------------------------------------- subroutine calc_tri( ) implicit none real*8 data1(3,200000) !<--- ここでエラー --> write(6,*) 'test b' !-------------------------------------------------- このような場合、配列データを減らす以外にどのような対策が あるのでしょうか? あるいはメモリ制限になりそうなデータ数が分る方法などあります でしょうか? 環境は linux (CentOS) intel Fortran Compiler version 8.0 Mem: 1GB topコマンドにて Memの使用割り合いは10%にもならないのですが コンパイラによるメモリ制限などもあるのでしょうか? subroutine内の配列の宣言はデータ数より多くとっていることは確認しています。

noname#29127
noname#29127

質問者が選んだベストアンサー

  • ベストアンサー
  • osamuy
  • ベストアンサー率42% (1231/2878)
回答No.1

スタックオーバフローを起こしているのでは。 ulimitとかでスタックサイズを引き上げるか、ALLOCATABLEな配列にしてヒープ領域を使うようにするとか。

noname#29127
質問者

お礼

皆様 回答ありがとうございます。用語や対策などについて色々勉強になります。 教えていただいた用語などを自分なりに調べて理解したいと思います。 ulimitに関しては制限をゆるくした状態で実行していました。 (記載していませんでした。) プログラムの止まる部分ですが、投稿に記載した部分に間違いがありました。 !-------------------------------------------------- subroutine calc_tri(cpsn) implicit none integer cpsn real*8 data1(3,cspn) !<--- ここでエラー --> write(6,*) 'test b' !-------------------------------------------------- cspnにはデータ数が入りまして、Fortranではこのような引数を用いてデータ サイズを確保する方法がとれますよね? 上記でも小さなデータの場合は問題ありませんが、大きなデータでは何故か問題が 出ます。下記のようにすればSegmentation Faultはでなくなりました。 real*8 data1(3,200000) !データ数は195000 cspnの値はsubroutine読みだし前に書き出した段階では正常な値でした。 メモリをたくさん使ったときにcspnの値がおかしくなったのでしょうか? ----------------------------------------------------------------------

その他の回答 (1)

  • xcrOSgS2wY
  • ベストアンサー率50% (1006/1985)
回答No.2

stack sizeかdata segment sizeの制限に到達したのでしょう。 ulimitないしlimitで制限値を変更できるようです。 "Google Answers: Understanding ulimit output" http://answers.google.com/answers/threadview?id=311442 「メモリの使用量を制限するには」 http://www.atmarkit.co.jp/flinux/rensai/linuxtips/537memulimit.html

noname#29127
質問者

お礼

ありがとうございます。 ulimitは使用していましたが、教えていただいたページではulimitの色々な使い方が掲載されていていいですね。 No.1さんへの回答で記載のようにとりあえずエラーはでなくなりました。

関連するQ&A

  • fortranでsegmentation faultが出る

    初めまして。fortran77のとあるプログラム群を扱っているのですが、配列の添字を決めているparameterの数を大きくするとsegmentation faultが出てしまいます。 integer ABC parameter (ABC = 200000) !この値を大きくすると出ます。 hairetsu(ABC) こんな感じです。 プログラムはcygwinで走らせてます。 どなたか解決方法を教えていただけないでしょうか?

  • Segmentation fault

    最短経路問題を解くプログラムを作って完成したのですが、でる時は連続して出てしまうのですが Segmentation fault (core dumped) と表示されてしまいプログラムが実行中なのに途中で終わってしまいます.ほんとうならネットワークの直径が表示されるんですが。。 gcc daijkstra.c ./a アクセスポイント>>> 90 全ネットワーク数>>> 50 Segmentation fault (core dumped) (表示された場合.) gcc daijkstra.c ./a アクセスポイント>>> 90 全ネットワーク数>>> 50 直径>>>>4.432 (成功した場合.)

  • fscanf Segmentation fault

    すいません。Segmentation faultがでてプログラムが動きません・・・原因がわからないのでわかる方がおられましたら教えてください。 FILE* Bank::setFp( const char c[]){ if(fp!=NULL){ fclose(fp); }else{ fp = fopen("c[]","r"); } return fp; } Bank::Bank(char c[]){ fp = 0; size = 0; arraySize = 0; int some = 0 ; int bal; char ac[16]; char cust[316]; fp = setFp(c); fscanf(fp, "%d:",&some); grow(arraySize+10); for(int i=1 ; i<arraySize ; i++){ fscanf(fp, "%[^,],%d,[^;];",arraySize,ac,&bal,cust); savings[i].init(cust,ac,bal); size++; fclose(fp); } } ちなみにSegmentation fault は fscanf(fp, "%d:",&some);を作動した時にでました。 ちなみにサンプルデータは、 3:423423454567987,9234617,Woo,Charles,Winnipeg,416-555-5558;523423454567987,2534,DeJesus,Pancho,Edmonton,416-555-5559;623423454567987,543876,Smith,Bob,Charlottetown,416-555-5544; です。 メインプログラムでは、Bank one("a34.dat");と読んでるだけです。 よろしくお願いします

  • Segmentation fault その2

    ダイクストラ法を用いて最短経路を表示するプログラムなんですが void daijkstra(int a) { //count[] この関数では定義していません(この外です) int g, b, c, d, e, f; //アクセス出来る点を探索. for(b = 0, c = 0;b != ten;b++){ if(adj[a][b] == INT_MAX || a == b) continue; else{ if(no_loop[b] != ten * hen){ count[c] = b;//アクセス出来た点を入力. c++; no_loop[b] = no_loop[b] + 1; } } } count[c] = -1; for(d = 0;count[d] != -1; d++){ c = count[d]; if(place[c] == INT_MAX){ place[c] = adj[a][c] + place[a]; } else{ g = adj[a][c] + place[a]; if(g < place[c]){ place[c] = g; } } } for(e = 0;count[e] != -1;e++){ f = count[e]; daijkstra(f); } return; } こういった感じに完成しました。 ですがSegmentation fault (core dumped)と表示されどうしても出来ない場合が時々あるんです.(main 関数でネットワークをランダムに生成しています。上記の関数だけでは情報が少ない場合はmainを載せます。) スタックオーバーフロウが起きているのは確実なんですがそれを回避する術を知らないのでどうかご協力をお願いします. ten * hen を1に変更すると2回目にアクセスした場合に2回目の方が短い場合更新できなくなるので1以上にして、ten * henは全ての点に全部の辺が付いていると考えた『これ以上はないはず』といういみがあります

  • fortranでプログラムをつくったのですが

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

  • fortran 配列宣言のオーバーフロー

    fortranの配列宣言について質問です。 下記の様に配列の変数をサブルーチンの内外で宣言することで違いが出てきました。 こういうものなのでしょうか。失礼します。 parameter(ine=4999) c call test1(ine) !error call test2() !OK stop end subroutine test1(ine) dimension ary1(ine,50) return end subroutine test2() parameter(ine=4999) dimension ary1(ine,50) return end

  • C言語 Segmentation fault

    program SPROGRAM 17 4 pas104 SIDENTIFIER 43 4 ( SLPAREN 33 4 上記のようなファイルを読みこんで、1行づつ各トークン(programとか17とか)を構造体に格納する関数reader()を作りましたが、これを以下のparser.cで呼びだすと「Segmentation fault(core dumped)」となってしまいます。gdbのrunコマンドでプログラムを実行すると、関数を呼び出す所で Program received signal SIGSEGV, Segmentation fault. 0x0040140f in reader () と表示されました。が,どうすればよいか全然分かりません・・・ どうすれば正しく動作してくれるのか、どなたか教えてください・・・ 以下ソース /*read.c*/ #include "head.h" void reader(void) { fprintf(stdout,"check"); char buf[BUF_LEN]; if (fgets(buf,sizeof(buf),fp) == NULL)/*ここで1行読みこむ*/ {/*いきなりNULLの場合*/ strcpy(t.str, ""); t.num = SEOF; t.line = 1; } else { 省略 } return; } /*parser.c*/ #include "head.h" struct tokenbox t; FILE *fp; int main(int argc, char *argv[]) { if (argc != 2)/*引数チェック*/ { fprintf(stderr,"Usage: (./parser) (file.ts)\n"); return -1; } int len; len = strlen(argv[1]);/*file.ts の長さ取得*/ if((argv[1][len-1] == 's') && (argv[1][len-2] =='t') && (argv[1][len-3] == '.'))/*tsファイルが指定されているかどうか*/ { fp = fopen(argv[1],"r");/*ファイルオープン*/ if (fp == NULL) { fprintf(stderr,"Such ts file is not exist\n"); return -1; } fprintf(stdout,"authenticate ts file!\n");//←これは出力される reader(); //←ここでSegmentation faultと思われる printf("t.str = %s\n", t.str); printf("t.str[0] = %c\n", t.str[0]); printf("t.num = %d\n", t.num); printf("t.line = %d\n", t.line); fclose(fp); return 0; } else { fprintf(stderr,"the file is not ts\n"); return -1; } } ヘッダファイル一部抜粋 /*head.h*/ #include <stdio.h> #include <string.h> #include <stdbool.h> #define BUF_LEN 128 #define TOKEN_LEN 128 struct tokenbox {/*tsファイルの各情報を格納する構造体*/ char str[TOKEN_LEN]; int num; int line; }; extern struct tokenbox t;/*構造体をtと置く*/ extern FILE *fp; /*ファイルポインタ*/

  • fortran 配列受け渡し時の次元の一致

    fortran90、コンパイラはifortです。 普通メインプログラムとサブルーチン間での配列の受け渡しは、次元を揃えて渡すと思います。 とあるコード(以後コードA)を読んでいると、2次元配列を渡し、1次元配列で受け取っていました。 例 program test1 integer :: a(3,3) call testsub(a) end program subroutine testsub(b) integer :: b(9) end subroutine これが受け取り側でどう処理されているのかわからず、調べるために適当なテストコードを書きました。 a 123 456 789 ↓ b 123456789 になるとか 結果、コンパイルは通ったのですがサブルーチン側では全て0で置き換えられてしまいました。 コードAはpgiかなんかでコンパイルしていたようなのでコンパイラの違いでしょうか? よくわらなかったので質問させて頂きました。 質問をまとめますと、 (1)次元の異なる配列の受け渡しができるかどうか (2)その場合中身はどうなるか よろしくお願いします。 ---以下テストコード--- program testa implicit none integer :: a(3,3),i,j do i=1,3 do j=1,3 a(i,j)=j+(i-1)*3 enddo enddo do i=1,3 do j=1,3 write(6,*) a(i,j) enddo enddo call sub1(a) end program subroutine sub1(b) integer :: b(9),i do j=1,9 write(6,*) b(i),'sub' enddo end subroutine

  • Fortran の配列使用に必要なメモリについて

    Fortranで数値計算をしています。 配列に必要なメモリの計算方法について質問させてください。 例えば、real(4),real(8),real(10),integer,などでそれぞれ a(10,10) と宣言した配列を用いた計算に必要なメモリはいくらになるでしょうか? よろしくお願いします。

  • GNUコンパイラとIntelコンパイラの違いについて

    今回fortranとC言語で書かれたWindows用プログラムをLinux用に移植することになりました。GNUのコンパイラを使用し無事コンパイルできたので実行したのですが"Segmentation fault"となりうまく実行できませんでした。そこで試しにIntelのコンパイラを使用しコンパイルしてみたところGNUのときとは違い"Segmentation fault"とは出ず、プログラム内のエラーチェックに引っかかり止ってしまいました。同じソースコードにもかかわらず止まる箇所が異なります。 今まで考えたことがなかったのですがGNUとIntelのコンパイラの違いはなんなのでしょうか?また、この二つ以外にいいコンパイラはあるのでしょうか?

専門家に質問してみよう