質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Windows 7

Microsoft Windows 7は過去にリリースされたMicrosoft WindowsのOSであり、Windows8の1代前です。2009年の7月にリリースされ販売されました。Windows7の前はWindowsVistaで、その更に3年前にリリースされました。

Q&A

解決済

3回答

3556閲覧

c言語のプログラムを実行すると強制終了してしまう

S.Abe

総合スコア8

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Windows 7

Microsoft Windows 7は過去にリリースされたMicrosoft WindowsのOSであり、Windows8の1代前です。2009年の7月にリリースされ販売されました。Windows7の前はWindowsVistaで、その更に3年前にリリースされました。

0グッド

0クリップ

投稿2018/07/09 06:33

編集2018/07/09 06:48

前提・実現したいこと

win7のgcc環境において、以下のプログラムでルンゲクッタ法による数値計算を行おうとしています。gccでのデバッグは問題ないのですが、プログラムを実行すると強制終了を起こしてしまいます。原因が特定できていませんので、修正方法をご教授頂きたいです。

#include <stdio.h> #include <math.h> double f1(double t,double u,double v); double f2(double t,double u,double v); int main(void) { FILE *output; output = fopen("output.dat","w"); double t = 0.0; double dt = 0.01; double delta = 0.1; double r[3000][3000]; double u = 1.0, w = 1.0;//初期値 double a=0.03, b=0.10;//論文での値 double k0[2][2], k1[2][2], k2[2][2], k3[2][2];//計算した値を入れる配列 //離散化を構成する int i; int n,s,p;//mpとmqの添え字 double mp,mq; double u2[3000][3000]; double w2[3000][3000]; //double u2[0][0]=0.0;//初期化 //double w2[0][0]=0.0;//初期化 u2[s][n]=1.0; w2[s][n]=1.0; for(n=0;n<=3000;n++){ for(s=0;s<=3000;s++){ for(n=0;n<=3000;n++){ u2[s+1][n] = (mp*u2[s][n] + delta*(2*mp*u2[s][n]*w2[s+1][n]+a) )/1 + delta*(w2[s+1][n]*w2[s+1][n]+a+1); w2[s+1][n] = (mq*w2[s][n] + delta*(mp*u2[s][n]*(mq*w2[s][n]*w2[s][n]+1)+b) )/1 + delta*(w2[s+1][n]*w2[s+1][n]+a+1); } } mp = 0.5*(u2[s][n+1]+ u2[s][n-1]); mq = 0.5*(u2[s][n+1]+ u2[s][n-1]); for(t = 0.0; t <=3000; t+=dt) {//ルンゲクッタ法で計算 k0[0][0]=dt*f1(t,u,w); k0[1][1]=dt*f2(t,u,w); k1[0][0]=dt*f1(t+dt/2.0,u2[s+1][n]+k0[0][0]/2.0,w2[s+1][n]+k0[1][1]/2.0); k1[1][1]=dt*f1(t+dt/2.0,u2[s+1][n]+k0[0][0]/2.0,w2[s+1][n]+k0[1][1]/2.0); k2[0][0]=dt*f1(t+dt/2.0,u2[s+1][n]+k1[0][0]/2.0,w2[s+1][n]+k1[1][1]/2.0); k2[1][1]=dt*f1(t+dt/2.0,u2[s+1][n]+k1[0][0]/2.0,w2[s+1][n]+k1[1][1]/2.0); k3[0][0]=dt*f1(t+dt,u2[s+1][n]+k2[0][0],w2[s+1][n]+k2[1][1]); k3[1][1]=dt*f1(t+dt,u2[s+1][n]+k2[0][0],w2[s+1][n]+k2[1][1]); u2[s+1][n] = u2[s][n] + (k0[0][0]+ k1[0][0]*2 + k2[0][0]*2 + k3[0][0])/6.0; w2[s+1][n] = w2[s][n] + (k0[1][1]+ k1[1][1]*2 + k2[1][1]*2 + k3[1][1])/6.0; fprintf(output,"%lf, %lf, %lf\n", u2[s+1][n] , w2[s+1][n], t); printf("%lf , %lf , %lf\n",u2[s+1][n] , w2[s+1][n], t); } } fclose(output); return 0; } double f1(double t,double u,double w){ int n,s; double r[3000][3000]; double a=0.04; double u2[3000][3000]; double w2[3000][3000]; r[s+1][n] = -u2[s+1][n]*w2[s+1][n]*w2[s+1][n]+a*(1-u2[s+1][n]); return 0; } double f2(double t,double u,double w){ int n,s; double r[3000][3000]; double b=0.11; double u2[3000][3000]; double w2[3000][3000]; r[s+1][n] = u2[s+1][n]*w2[s+1][n]*w2[s+1][n] - b*w2[s+1][n]; return 0; }

発生している問題・エラーメッセージ

gccは通るのですが、プログラムを実行すると強制終了してしまいます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

突っ込みどころはたくさんありますね。
ざっと気づいたところ。

c

1 u2[s][n]=1.0; 2 w2[s][n]=1.0;

snを初期化していないので、どこが初期化されるかわかりません。

c

1 for(n=0;n<=3000;n++){ 2 for(s=0;s<=3000;s++){ 3 for(n=0;n<=3000;n++){

nのループが2回入れ子になってる。
ループ回数が0~3000になってる。
配列の要素は0~2999です。

c

1 for(s=0;s<=3000;s++){ 2 for(n=0;n<=3000;n++){ 3 u2[s+1][n] = (mp*u2[s][n] + delta*(2*mp*u2[s][n]*w2[s+1][n]+a) )/1 + delta*(w2[s+1][n]*w2[s+1][n]+a+1); 4 w2[s+1][n] = (mq*w2[s][n] + delta*(mp*u2[s][n]*(mq*w2[s][n]*w2[s][n]+1)+b) )/1 + delta*(w2[s+1][n]*w2[s+1][n]+a+1); 5 }

u2[s+1][n]では、最大でu2[3001][3000]を参照することになり、確保していない領域を参照することになります。

c

1 double k0[2][2], k1[2][2], k2[2][2], k3[2][2];//計算した値を入れる配列

コード内で使ってる要素は[0][0][1][1]なので、二次元配列にする意味がない。

コード全体を通して、[3000][3000]の配列。

初期化せずに使っている。
またサイズが大きすぎてスタックオーバーしているはず。
グローバル変数にするかstatic変数にしてください。

投稿2018/07/09 07:41

ttyp03

総合スコア16998

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

S.Abe

2018/07/10 04:23

細かいところまでご指摘ありがとうございました。何とか修正できましたのでベストアンサーにさせていただきます。
guest

0

関数内で3000x3000なdoubleの配列が3つも宣言されてますのでスタックオーバーフロー起こしてたりしませんか?
3000x3000って900万になりますけどスタック領域そんなに無いですよね?
mallocで確保するとかしなくて大丈夫です?

投稿2018/07/09 07:27

HiroshiWatanabe

総合スコア2160

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

まず問題になりそうなのはここですかね。

C

1int main(void) { 2 FILE *output; 3 output = fopen("output.dat","w"); 4 5 double t = 0.0; 6 double dt = 0.01; 7 double delta = 0.1; 8 double r[3000][3000]; 9 double u = 1.0, w = 1.0;//初期値 10 double a=0.03, b=0.10;//論文での値 11 double k0[2][2], k1[2][2], k2[2][2], k3[2][2];//計算した値を入れる配列 12 13 //離散化を構成する 14 int i; 15 int n,s,p;//mpとmqの添え字 16 double mp,mq; 17 double u2[3000][3000]; 18 double w2[3000][3000]; 19 //double u2[0][0]=0.0;//初期化 20 //double w2[0][0]=0.0;//初期化 21 u2[s][n]=1.0; // ① 22 w2[s][n]=1.0; 23 24 for(n=0;n<=3000;n++){ 25 for(s=0;s<=3000;s++){ 26 for(n=0;n<=3000;n++){ // ② 27

まず①ですが、u2[s][n] にアクセスしようとしていますが、s, n が 初期化されていません
デバッガを介した場合は 0 クリアされていることがありますが、デバッガを介さないと s, n に何が入っているか分かったものではありませんから、変な場所にアクセスして segmentation fault で落ちますな。

そして②ですが、一番大きいループで n を回しているのに、その中でまた n を回すって、何がやりたいんですか?

投稿2018/07/09 06:54

tacsheaven

総合スコア13703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問