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

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

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

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

Q&A

解決済

4回答

976閲覧

C言語 segmentation fault

north_redwings

総合スコア32

C

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

0グッド

0クリップ

投稿2017/12/09 10:31

C言語の行列の計算です.
NNの正方行列とN1のベクトルの掛け算で動的確保の勉強です.
Nをとりあえずdefineで定義しているのですが,N=2,4,5あたりは問題なく作動するのですが,N=3,8,9あたりは必ずsegmentation faultと出てしまいます.(このエラーについてはよくわかっていません)
以下がコードです.行列の動的確保のコードは授業で配布された物を使用しており,まだしっかりとは解釈できていませんがとりあえず見よう見まねで使いました.

C

1#include <stdio.h> 2#include <stdlib.h> 3#define N 3 4 5double **dmatrix(int, int); /* 行列領域の確保 */ 6double *dvector(int ); /* ベクトル領域の確保 */ 7 8int main(void) { 9 double **mat_A; /* ポインタへのポインタ */ 10 double *vec_x, *vec_b; 11 12 printf("N=%d\n",N); 13 14 mat_A = dmatrix(N, N); /* 領域確保 */ 15 vec_x = dvector(N); 16 vec_b = dvector(N); 17 18 for(int s=0;s<N;s++){ 19 for(int t=0;t<N;t++){ 20 mat_A[s][t] = (double)(s+t); 21 vec_x[s] = (double)s; 22 vec_b[s] = (double)0; 23 printf("mat_A[%d][%d]=%lf, vec_x[%d]=%lf, vec_b[%d]=%lf\n",s,t,mat_A[s][t],s,vec_x[s],s,vec_b[s]); 24 } 25} 26 27 28 for(int i=0;i<N;i++){ 29 for(int j=0;j<N;j++){ 30 vec_b[i] += mat_A[i][j]*vec_x[j]; 31 } 32} 33 for(int k=0;k<N;k++){ 34 printf("\n b[%d]=%lf \n",k,vec_b[k]); 35 } 36 printf("\n"); 37 38 free(mat_A); 39 free(vec_x); 40 free(vec_b); 41 return 0; 42} 43 44double **dmatrix(int nr, int nc) { 45 double **mat; 46 mat = malloc(nr*sizeof(double *)); 47 if (mat == NULL) 48 puts("Failure!! (from (*dmatrix)[nr])"); 49 else { 50 int i, j; 51 double *base = malloc(nr*nc*sizeof(double)); 52 if (base == NULL) 53 puts("Failure!! (from dmatrix[nr][nc])"); 54 else { 55 for (i=0; i < nr; i++) 56 mat[i] = base + i*nc; 57 } 58 free(base); 59 } 60 return(mat); 61} 62 63double *dvector(int n) 64{ 65 double *vec= malloc(n*sizeof(double)); 66 if (vec == NULL) { 67 printf("Failure!! (from dvector) \n"); 68 exit(1); 69 } 70 return(vec); 71} 72 73 74

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

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

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

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

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

guest

回答4

0

ベストアンサー

バグの原因はすでに指摘されている箇所のfreeの呼び出しのせいです。

リファクタリングしてみました。少しは見やすいはず。

なお多くの指導教官はろくにC言語の標準規格なんて読んでませんし、安全に配慮したコードなんて書いたことがないので、教えられないのは致し方ありません。
挙句C言語の知識がC89(1989年に標準化、今から28年前!!!)で止まっていたりもっとひどいとその更に前、規格標準化前のK&R Cのころ(だいぶ文法が違う)だったり。

C言語の標準規格は、ANSI C89/ISO C90, (ISO C95), ISO C99, ISO C11となっており、もうすぐISO C17が出そうです。
C17 (not C++17) - Qiita
History of C - cppreference.com

c

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4 5#define N 3 6 7/// 行列の確保 8double** new_dmatrix(int nr, int nc) 9{ 10 double** mat = malloc(nr * sizeof(double*)); 11 if (mat == NULL) { 12 puts("Failure!! (from (*new_dmatrix)[nr])"); 13 exit(1); 14 } 15 double* base = malloc(nr * nc * sizeof(double)); 16 if (base == NULL) { 17 puts("Failure!! (from new_dmatrix[nr][nc])"); 18 exit(1); 19 } 20 for (int i=0; i < nr; i++) { 21 mat[i] = base + i*nc; 22 } 23 //DO NOT FREE THIS MEMORY BLOCK 24 //TO AVOID segmentation fault! 25 //free(base); 26 return mat; 27} 28 29///行列の開放 30void delete_dmatrix(double** mat) 31{ 32 free(mat[0]); 33 free(mat); 34} 35 36/// ベクトルの確保 37double* new_dvector(int n) 38{ 39 double *vec = malloc(n*sizeof(double)); 40 if (vec == NULL) { 41 printf("Failure!! (from new_dvector) \n"); 42 exit(1); 43 } 44 return vec; 45} 46 47/// ベクトルの開放 48void delete_dvector(double* vec) 49{ 50 free(vec); 51} 52 53int main(void) 54{ 55 printf("N=%d\n",N); 56 57 double** mat_A = new_dmatrix(N, N);// 領域確保 58 double* vec_x = new_dvector(N); 59 double* vec_b = new_dvector(N); 60 61 memset(vec_b, 0, N * sizeof(double)); 62 for(int s=0;s<N;s++){ 63 for(int t=0;t<N;t++){ 64 mat_A[s][t] = (double)(s+t); 65 vec_x[s] = (double)s; 66 printf("mat_A[%d][%d]=%lf, vec_x[%d]=%lf, vec_b[%d]=%lf\n" , s, t, mat_A[s][t] ,s, vec_x[s], s, vec_b[s]); 67 } 68 } 69 70 for(int i = 0; i < N; i++){ 71 for(int j = 0; j < N; j++){ 72 vec_b[i] += mat_A[i][j] * vec_x[j]; 73 } 74 } 75 for(int k = 0; k < N; k++){ 76 printf("\n b[%d]=%lf \n", k, vec_b[k]); 77 } 78 putchar('\n'); 79 80 delete_dmatrix(mat_A); 81 delete_dvector(vec_x); 82 delete_dvector(vec_b); 83 return 0; 84} 85

https://wandbox.org/permlink/Iq9g2CPMfPGpgKy4

投稿2017/12/09 14:23

編集2017/12/09 14:32
yumetodo

総合スコア5850

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

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

north_redwings

2017/12/09 14:40

本当に丁寧にありがとうございました. 助かりました! もっと勉強していきます!!!
guest

0

サイズnrncの領域を取ってサイズncの配列nr個に分けてmatrixにしているので、mat_aの実態はbase内にあります。

なのに baseをfreeしてしまっているので不安定な動作になっています。
あちこちに無駄な処理も含まれています。エラー処理も間違いがありますが、動作テストの範囲内ではメモリ割り当てに失敗することがないので顕在化はしてません。

とりあえず分かりやすさのためには、

else { int i; for (i=0; i < nr; i++)    mat[i] =dvector(nc); } }

のほうが見通しが良くなるでしょう。

投稿2017/12/09 11:37

a_saitoh

総合スコア702

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

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

north_redwings

2017/12/09 11:50

ありがとうございます! 教員から渡されたコードなのであまり考えずに使ってしまいました。要反省ですね…やり直してみます!
yumetodo

2017/12/09 14:13

このfreeが原因ですね。その後のmain内のmat_A[s][t]が不正アクセスになる
north_redwings

2017/12/09 14:21

今完全に出来上がりました、ありがとうございます! 教員でも間違えるんですね…確認してから配布してると思ったんですが…笑。
a_saitoh

2017/12/09 23:55

プログラミングに限らず、教員の担当科目は必ずしも教員自身の理解度を確保して割り当てられてはいないので。
guest

0

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

僕も調べてみたんですがどうやらメモリ関連のエラーみたいですね…。
行列の動的確保の部分は解釈出来ていないのと教員から渡されたコードなので(それでもミスがあって自分で直したつもりなのですが)、さらに全ての値のときだけ…値が大きくなると…コンパイル時にランダムで…などではなく上記の通り特定の値のときだけこうなってしまうので尚更困っています…。

もし後に判明しましたら回答の程よろしくお願いします。

投稿2017/12/09 11:18

north_redwings

総合スコア32

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

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

0

とりいそぎエラーメッセージの意味だけ。
segmentation fault
はLinux等において不正なメモリアクセスがあったときに発生します。たとえば、有効アドレスを示していないポインタを辿って変数書き込みした場合などがこの例です。

投稿2017/12/09 10:57

HogeAnimalLover

総合スコア4830

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

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

north_redwings

2017/12/09 11:18

迅速な回答ありがとうございます。 僕も調べてみたんですがどうやらメモリ関連のエラーみたいですね…。 行列の動的確保の部分は解釈出来ていないのと教員から渡されたコードなので(それでもミスがあって自分で直したつもりなのですが)、さらに全ての値のときだけ…値が大きくなると…コンパイル時にランダムで…などではなく上記の通り特定の値のときだけこうなってしまうので尚更困っています…。 もし後に判明しましたら回答の程よろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問