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

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

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

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

Q&A

解決済

2回答

5704閲覧

セグメントエラーで実行されません

tsuji

総合スコア7

C

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

0グッド

0クリップ

投稿2017/01/28 03:04

編集2017/01/28 03:15

ソースコードを分割してコンパイルする課題を行っています。そこでコンパイルしたファイルを実行しようとしてもセグメントエラーが表示されてしまいます。誤りを自分でも探してみたのですがどうしても見つかりません。よろしければ原因を教えてもらえないでしょうか。よろしくおねがいします。

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

”xの値を入力 >” までの処理しか行われない。

###該当のソースコード

mylib.h

double fctrl(int); double taylor(double,int);

ex2-2

#include<stdio.h> #include<math.h> #include"mylib.h" int main(void){ double x,err; int n; printf("xの値を入力 >"); scanf("%lf",&x); err=1; for(n=0;err>=0.005;n++){ err = fabs(exp(x)-taylor(x,n)); } printf("第%d項まで展開する必要がある\n",n); return 0; }

fctrl.c

double fctrl(int n){ if(n==0){ return 1; }else{ return n*fctrl(n-1); } }

taylor.c

#include<math.h> double taylor(double x, int n){ if(n==0){ return 1; }else{ return pow(x,n)/fctrl(n)+taylor(x,n-1); } }

###試したこと
ex2-2がどこまで処理されているのか確かめたところscanfのあたりから処理されていないところまでわかりました。

###補足情報(言語/FW/ツール等のバージョンなど)
コンパイルはgcc -o ex13 mylib.h ex2-2.c fctrl.c taylor.c -lm の形で行いました。

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

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

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

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

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

mit0223

2017/01/28 03:08

言語はC言語ですよね。C#になっているので、修正してもらえますか。
guest

回答2

0

ベストアンサー

こんにちは。

xに小さな値を入れれば計算終了します。
35までは終了し、36は終了しませんでした。
taylor展開計算の中で何かオーバーフローが発生しているようです。
指数関数の増え方は爆発的ですから、意外に簡単にオーバーフローします。

ちなみに下記の文をループの中に入れることで解りました。

printf("[%d] err=%f exp(x)=%f taylor(x,n)=%f\n", n, err, exp(x), taylor(x,n));


【追記】
fctrl(n)のところで警告がでてましたのでtaylor.cに#include"mylib.h"を補なってます。
この#include無しの場合、コンパイラはint fctrl(int n)と解釈している筈なので、そこで落ちたのかも知れません。

投稿2017/01/28 03:27

編集2017/01/28 03:30
Chironian

総合スコア23272

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

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

tsuji

2017/01/28 03:48

回答ありがとうございます! fctrl(n)のところを完全に見落としていました。おかげで無事実行することができました。本当にありがとうございます!
guest

0

根本原因はプロトタイプ宣言をせずに関数を呼び出すコードを書いているためだと思います。
対処はtaylor.cの先頭に#include "mylib.h"を追加することです。

コンパイラーが「宣言なしに関数を呼び出している」という警告を発しているはずですがそれを無視してしまったのですね。

fctrlという階乗を計算する関数をtaylor.cでプロトタイプ宣言なしに呼び出しています。C言語ではこういう関数呼び出しを書いてしまうと「戻り値の型をintと仮定」してコンパイルしてしまいますがプログラムのバグの可能性があるととらえてコンパイラーがその旨の警告を発します。

典型的なPCの環境ではintは32bit, doubleは64bit(IEEE形式)になると思いますが、taylor.cのコンパイル時にfcntlの戻り値が「intである」という間違った仮定でネイティブコードが生成されると、fctrlが本来返しているdouble型の値とは全然違う値をtaylor関数で受け取ってしまい、その値に基づいて計算した結果おかしな値になってしまったのでしょう。

ご質問のコードではテイラー展開の計算を再帰的アルゴリズムで行っています。計算誤差が一定以上の間、テイラー展開式の項数を増やしながら誤差が減っていくことを期待したプログラムなのですが前述のバグによって値が収束しないため項数nがどんどん巨大になってしまいある時点でスタックオーバーフローを起こしsegmentation violationが発生したのだと思います。


訂正:
上の回答間違ってました。
fctrlは標準ライブラリーのfctrlの方がが呼ばれちゃったんですね・・・標準ライブラリーの方のfctrlが正しくない引数で呼び出されたために異常終了したんだと思います。
できるだけ標準ライブラリーに存在する関数名を使わないように注意できるといいかも知れませんね。例えば階乗はfactorialにしておくとか。(factorialもあったりして・・・)

投稿2017/01/28 04:14

編集2017/01/28 05:07
KSwordOfHaste

総合スコア18394

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

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

tsuji

2017/01/28 04:30

回答ありがとうございます! 警告は「fctrlがビジー状態です」と表示されたのですが、よく意味がわからずコンパイルもされるため軽視していました…。詳しく説明もしていただきありがとうございます!
KSwordOfHaste

2017/01/28 05:01

あ・・・標準ライブラリーのfctrl(ファイルの制御をするための関数)が呼ばれたんですね。上の回答は間違いでした(w;)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問