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

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

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

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

2259閲覧

Segmentation fault: 11について

Leita

総合スコア13

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/04/21 06:20

編集2019/04/21 06:42

前提・実現したいこと

ニュートン法の問題を解くプログラムをC++で作成しています。
z^3-1 = 0となるz= 1となるように解くことのできる初期値を求めるプログラムです。
初期値は-2 =< x <= 2 -2 <= y <= 2の間を500等分した点を予め求めておいて(0、0)となる原点のみ省いたもの配列に保存して、その後予め求めたx yそれぞれについての漸化式を用いて、収束するかどうかを判定し、z=1に収束する組のみを保存するつもりで書きました。

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

実行すると計算そのものは表示され実行されているのですが、(条件分岐も通っています)
ある程度まで実行すると下記のエラーが発生し止まってしまいます。
Segmentation fault: 11
どこの部分で起こっているのか教えていただきたいです。

該当のソースコード

#include <iostream> #include <math.h> using namespace std; double f(int x) { double num = exp(-(x * x)) - sin(x); return num; } double dff(int x) { double num = -2 * exp(-(x * x)) - cos(x); return num; } int main(void) { long int counter = 0; double x = 0; double y = 0; double x1 = 0; double y1 = 0; double x_init = 0; double y_init = 0; double xh[500]; double yh[500]; double app = 4.0 / 500.0; double num = -2; double ans_x[25000]; //収束する初期値の保存する配列、余剰のために25000取ってあります double ans_y[25000]; for (int i = 0; i < 500; i++) {//ここで初期値を生成しています(ここだけだとエラーは出ていません) if (i == 250) { num += app; xh[i] = num; yh[i] = num; } else { xh[i] = num; yh[i] = num; } num += app; } for (int i = 0; i < 500; i++) { x = xh[i]; x_init = x; for (int t = 0; t < 500; t++) { y = yh[t]; y_init = y; while (1) { cout << "x1:" << x1 << " " << "y1:" << y1 << endl; x1 = (2.0 * x) / 3.0 + ((x * x) - (y * y)) / (3 * (x * x + y * y) * (x * x + y * y)); y1 = (2 * y) / 3 - (2 * x * y) / (3 * ((x * x + y * y) * (x * x + y * y))); if ((abs(x1 - x) < 1.0e-6) && (abs(y1 - y) < 1.0e-6)) {//収束判定です。この時点ではz = 1に収束するかわからないので次で判定します。 if (abs(sqrt(pow(1 - x1, 2) + pow(y1, 2))) < 1.0e-6) {//ここで完全に判定します。 ans_x[counter] = x_init; ans_y[counter] = y_init; counter += 1; break; } break; } x = x1; y = y1; } } } cout << "finish" << endl; }

試したこと

デバッガに慣れておらずあまりに回数の多い処理のデバッグができず、非常に苦慮しています。どこの部分を改善すべきかご教示いただけると幸いです。

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

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

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

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

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

cateye

2019/04/21 06:31

ソースは<code>の```と```の間に貼り付けましょう。
Leita

2019/04/21 06:41

すいません不慣れで失礼しました 修正します。
guest

回答4

0

ans_x[]ans_y[] の要素数が少なすぎるようです。
当方でトレースを入れて確認したところ counter93000 以上になるようです。

double ans_x[95000]; double ans_y[95000];

くらいにすると正常に終了しました。

投稿2019/04/21 10:17

Bull

総合スコア986

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

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

Leita

2019/04/21 13:14

想定では最大で25000になるはずだったのでcounterの値が大きくなる原因を探してみます ありがとうございます
guest

0

ベストアンサー

67行目あたり、counterの値をprintfしてみると、
普通にans_x, ans_yの要素数(25000)以上になっているように見えます。
配列範囲外アクセスが原因ではありませんか?

以下、こちらでの実施例です。(53行目あたりのcoutはログが出すぎるので、消しました)

cpp

1 65 ans_x[counter] = x_init; 2 66 ans_y[counter] = y_init; 3 67 counter += 1; 4 68 cout << "counter: " << counter << endl; 5 69 break;
counter: 26703 counter: 26704 counter: 26705 counter: 26706 counter: 26707 counter: 26708 [1] 15068 segmentation fault (core dumped) ./a.out

投稿2019/04/21 10:14

sin_250

総合スコア112

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

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

0

とりあえず、配列の定義はグローバル変数(関数の外)でやってみましょう
今どきのPC/コンパイラではスタック領域は数Mbyteとられてるようなんでこれぐらいでは大丈夫でしょうけど、やっぱり大容量の配列をローカル変数で確保するのはちとキモチワルイですね


よくみると、counterは、500*500の値になるんでしょね?
そいつでアクセスする配列はサイズはいくつでしたっけ

投稿2019/04/21 07:07

編集2019/04/21 10:08
y_waiwai

総合スコア87774

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

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

Leita

2019/04/21 07:41 編集

関数外で定義を行なって再度実行してみたところBus error: 10が出ました。 確かめてみたところ最後の判定時に配列に格納するとこでエラーが出ているようでした
y_waiwai

2019/04/21 10:05

ならその最後の判定時とやらのところで範囲外になってるのでは。 デバッガでそこで止めて、インデックスがいくつになってるのかみてみれば
Leita

2019/04/21 13:16

最大で25000を想定していたので、whileから抜けるのがうまくできていないみたいです ありがとうございます
guest

0

私の環境(Linxmint19.1 + clang9)では発生しませんでしたが?

text

1x1:0 y1:0 2x1:-1.33333 y1:-1.375 3x1:-0.891684 y1:-1.00749 4x1:-0.61683 y1:-0.854444 5x1:-0.505705 y1:-0.85452 6x1:-0.499835 y1:-0.866044 7x1:-0.5 y1:-0.866025 8x1:-0.5 y1:-0.866025 9x1:-0.402991 y1:-1.36532 10x1:-0.406784 y1:-0.999533 11x1:-0.476081 y1:-0.866232 12x1:-0.500267 y1:-0.86551 13x1:-0.5 y1:-0.866025 14x1:-0.5 y1:-0.866025 15x1:-0.403448 y1:-1.3604 16x1:-0.407751 y1:-0.997192 17x1:-0.476749 y1:-0.866018 18x1:-0.500262 y1:-0.865543 19x1:-0.5 y1:-0.866025 20x1:-0.5 y1:-0.866025 21x1:-0.40391 y1:-1.35549 22x1:-0.408721 y1:-0.994866 23x1:-0.477407 y1:-0.865814 24x1:-0.500256 y1:-0.865575 25割愛 26x1:-0.402991 y1:1.36532 27x1:-0.406784 y1:0.999533 28x1:-0.476081 y1:0.866232 29x1:-0.500267 y1:0.86551 30x1:-0.5 y1:0.866025 31x1:-0.5 y1:0.866025 32x1:-0.402537 y1:1.37024 33x1:-0.405821 y1:1.00189 34x1:-0.475405 y1:0.866456 35x1:-0.500273 y1:0.865474 36x1:-0.5 y1:0.866025 37finish 38usr ~/Project/test/teratail %

投稿2019/04/21 06:43

編集2019/04/21 06:50
cateye

総合スコア6851

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

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

cateye

2019/04/21 07:00 編集

通常Segmentation faultは配列などのインデックスが範囲外の時に起こるのですが、そのへんを確認されたらどうでしょう?・・・ひょっとして?ですが、メモリが足りないのでは? 環境(処理系)がわからないのでなんとも言えませんがans_x,ans_yで400KB程度使いますから・・・一度外部変数にして試されたらいかがでしょう。
Leita

2019/04/21 06:56

一応確認して、配列あたりで範囲外を超えないように多めに配列の要素を増やしてみたのですが結果が変わらなかったです...
Leita

2019/04/21 13:16

一応8GBあるので大丈夫だと思っていたのですが、どうもcounter周りがおかしいようなので確認します ありがとうございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問