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

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

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

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

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

Q&A

2回答

1620閲覧

特定の順番で関数を呼び出すとセグフォが起きる

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

0グッド

1クリップ

投稿2019/07/21 09:10

編集2019/07/21 09:16

前提・実現したいこと

cで2値画像のラベリングをし,ラベリングをもとに画像からノイズを消去しようとしています.
ラベリングの関数が完成したので,ノイズを消去する関数を作成し,その関数内からラベリング関数を呼び出そうとすると,segmentation faultが発生しました.
どうやらラベリング関数内でセグフォは起きているようですが,原因がわかりません.

64*64で0,1で構成された画像をcharの二次元配列に読み込み,ラベリングでは画像の1となっているピクセルを2以上の数字でラベリングしています.ノイズの消去ではラベリングしたものをラベルごとに見て,ピクセル数が5以下のラベルのパーツをノイズとみなして消去し,最後にラベリングされたピクセルを1に戻すという作業を行なっています.

該当のソースコード

c

1#include <stdio.h> 2#include <stdlib.h> 3 4#define IMGSIZE 512 5#define NOISESIZE 5 6 7void PrintImg( unsigned char data[512] ) 8{ 9 unsigned char mask; 10 for(int x=0;x<64;x++){ 11 for(int y=0;y<8;y++){ 12 mask=0x80; 13 for(int i=0;i<8;i++){ 14 if(data[8*x+y] & mask) 15 printf("*"); 16 else 17 printf("o"); 18 19 mask=mask>>1; 20 } 21 } 22 printf("\n"); 23 } 24 25} 26 27void ExpandImg(unsigned char data[512],char img[64][64]){ 28 unsigned char mask; 29 for(int y=0;y<64;y++){ 30 for(int x=0;x<8;x++){ 31 mask=0x80; 32 for(int i=0;i<8;i++){ 33 if(data[8*y+x] & mask) 34 img[y][8*x+i]=1; 35 else 36 img[y][8*x+i]=0; 37 mask=mask>>1; 38 } 39 } 40 } 41} 42 43void PrintPattern( char img[64][64] ) 44{ 45 int x, y, i ; 46 47 for( y = 0 ; y < 64 ; y++ ) { 48 for( x = 0 ; x < 64 ; x++ ) { 49 putchar( img[y][x] ? '*' : 'o' ) ; 50 } 51 putchar( '\n' ) ; 52 } 53} 54 55void NormalizeImg(char img[64][64]){ 56 int i=0; 57 int j=0; 58 int origin_x=-1; 59 int origin_y=-1; 60 int width=-1; 61 int height=-1; 62 63 for(i=0;i<64;i++){ 64 for(j=0;j<64;j++){ 65 if(img[j][i]==1 && origin_x<0) 66 origin_x=i; 67 68 if(img[i][j]==1 && origin_y<0) 69 origin_y=i; 70 71 if(origin_x>=0 && origin_y>=0) 72 break; 73 } 74 } 75 76 for(i=(64-1);i>=0;i--){ 77 for(j=0;j<64;j++){ 78 if(img[j][i]==1 && width<0) 79 width=i-origin_x; 80 81 if(img[i][j]==1 && height<0) 82 height=i-origin_y; 83 84 if(width>0 && height>0) 85 break; 86 } 87 } 88 89 double x_ratio=0.0; 90 double y_ratio=0.0; 91 int point_x=0; 92 int point_y=0; 93 char img_normalized[64][64]; 94 95 x_ratio=(double)width/64.0; 96 y_ratio=(double)height/64.0; 97 98 for(i=0;i<64;i++){ 99 for(j=0;j<64;j++){ 100 point_x=origin_x+(int)((double)j*x_ratio+0.5); 101 point_y=origin_y+(int)((double)i*y_ratio+0.5); 102 img_normalized[i][j]=img[point_y][point_x]; 103 } 104 } 105 106 for(i=0;i<64;i++) 107 for(j=0;j<64;j++) 108 img[i][j]=img_normalized[i][j]; 109} 110 111int label(char img[64][64]){ 112 unsigned char last_label=1; 113 unsigned char pix=0; 114 unsigned char op_label=0; 115 unsigned char max_label=0; 116 unsigned char table[255]; 117 char unused_labels[4]; 118 int i,j,k; 119 120 for(i=0;i<255;i++) 121 table[i]=i; 122 123 for(i=0;i<64;i++){ 124 for(int j=0;j<64;j++){ 125 if(img[i][j]==1){ 126 for(k=0;k<4;k++) unused_labels[k]=0; 127 if((i-1)>=0){ 128 k=0; 129 pix=img[i-1][j]; 130 if(pix>1){ 131 if((op_label!=0 && op_label>pix) || op_label==0){ 132 op_label=pix; 133 unused_labels[k]=pix; k++; 134 } 135 } 136 137 138 if((j-1)>=0){ 139 pix=img[i-1][j-1]; 140 if(pix>1){ 141 if((op_label!=0 && op_label>pix) || op_label==0){ 142 op_label=pix; 143 unused_labels[k]=pix; k++; 144 } 145 } 146 } 147 148 if((j+1)<64){ 149 pix=img[i-1][j+1]; 150 if(pix>1){ 151 if((op_label!=0 && op_label>pix) || op_label==0){ 152 op_label=pix; 153 unused_labels[k]=pix; k++; 154 } 155 } 156 } 157 } 158 159 if((j-1)>=0){ 160 pix=img[i][j-1]; 161 if(pix>1){ 162 if((op_label!=0 && op_label>pix) || op_label==0){ 163 op_label=pix; 164 unused_labels[k]=pix; k++; 165 } 166 } 167 } 168 169 if(op_label==0){ 170 op_label=last_label+1; 171 if(op_label>=255) 172 return 1; 173 }else{ 174 for(k=0;k<4;k++){ 175 if(unused_labels[k]==0) break; 176 table[unused_labels[k]]=op_label; 177 if(unused_labels[k]>max_label) 178 max_label=unused_labels[k]; 179 } 180 } 181 182 img[i][j]=op_label; 183 last_label=op_label; 184 185 op_label=0; 186 } 187 } 188 } 189 190 unsigned char origin_label; 191 for(k=2;k<=max_label;k++){ 192 last_label=table[k-1]; 193 if(table[k]!=(last_label+1) || table[k]!=last_label){ 194 origin_label=table[k]; 195 i=k; 196 while (table[i]==origin_label){ 197 table[i]=last_label+1; 198 i++; 199 } 200 k=i-1; 201 } 202 } 203 204 for(i=0;i<64;i++) 205 for(j=0;j<64;j++) 206 img[i][j]=table[img[i][j]]; 207 208 return 0; 209} 210 211void NoiseErase(char p[64][64],const int size){ 212 if(label(p)!=1){ 213 int label=2; 214 int max_label=0; 215 int i,j; 216 int num=0; 217 int *erase_label; 218 int count=0; 219 220 for(i=0;i<64;i++){ 221 for(j=0;j<64;j++){ 222 if(p[i][j]>max_label) 223 max_label=p[i][j]; 224 } 225 } 226 erase_label=(int*)malloc(max_label*sizeof(int)); 227 for(i=0;i<max_label;i++) 228 erase_label[i]=0; 229 for(;label<=max_label;label++){ 230 for(i=0;(i<64 || num>size);i++){ 231 for(j=0;(j<64 || num>size);j++){ 232 if(p[i][j]==label) 233 num++; 234 } 235 } 236 if(num<=size){ 237 erase_label[count]=label; 238 count++; 239 } 240 num=0; 241 } 242 for(i=0;i<64;i++){ 243 for(j=0;j<64;j++){ 244 if(p[i][j]>=2){ 245 for(int k=0;k<count;k++){ 246 if(p[i][j]==erase_label[k]){ 247 p[i][j]=0; 248 break; 249 } 250 } 251 if(p[i][j]>=2) 252 p[i][j]=1; 253 } 254 } 255 } 256 free(erase_label); 257 } 258} 259 260 261int main() 262{ 263 FILE *fp ; 264 char imgfile[0x80] ; 265 unsigned char data[IMGSIZE] ; 266 char img[64][64]; 267 268 printf( "画像ファイル名を入力してください:" ) ; 269 fscanf( stdin,"%s",imgfile ) ; 270 271 if( ( fp = fopen( imgfile, "rb" ) ) == NULL ) { 272 fprintf( stderr, "cannot open %s\n", imgfile ) ; 273 return 1 ; 274 } 275 276 while( fread( data, IMGSIZE, 1, fp ) ) { 277 PrintImg( data ) ; 278 ExpandImg( data, img ) ; 279 NoiseErase( img, NOISESIZE ) ; 280 NormalizeImg( img ) ; 281 //PrintPattern( img ) ; 282 printf( "次のデータを表示するにはリターンキーを押してください" ) ; 283 getchar( ) ; } 284 285 fclose( fp ) ; 286 return 0 ; 287}

試したこと

label()を呼び出す部分をNoiseErase()からコメントアウトし,label()もmain()から呼び出してみましたが,やはりlabel()内でセグフォが起きました.
ただ,NoiseErase()を先に呼び出すと問題なく動くようです.
NoiseErase()単体でも動きます.
もちろんそれではやらせたいことは実現できませんが...

補足情報(FW/ツールのバージョンなど)

gccでmacOS上でbuildしています

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

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

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

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

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

izmktr

2019/07/21 09:25

パット見た感じ、table[img[i][j]] がきになりますね 255を指定しているってことは、imgはunsigned charを想定しているけど、charだから負の値になってる? (unsigned charの全域をカバーするなら、256を指定するべきですね)
SHOMI

2019/07/21 09:30 編集

このままではデバッグ丸投げです。 まずはご自分でデバッグしてみてください。 「gdb segmentation fault」や「gdb SEGV」で検索すれば方法は出てきます。
guest

回答2

0

各所に printf と fflash 等を組み合わせたログ表示を仕込み, どこで起きているかを確認されては如何でしょうか.

投稿2019/07/21 14:33

jimbe

総合スコア12646

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

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

0

ぱっと目についたところで、

関数 void ExpandImg(unsigned char data[512],char img[64][64])
ここの img[y][8*x+i]=1; 、 xの最大値が 8なので、[8*x+i] > 64 となりませんか?

他にもありそうですが、取り合えず。

投稿2019/07/21 10:25

pepperleaf

総合スコア6383

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問