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

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

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

Cygwinは、Unixのような環境を、Windows上で構築させるコマンドラインインターフェースです。

Q&A

解決済

2回答

2066閲覧

cygwinでのSegmentation fault (コアダンプ)

Ghostrick

総合スコア14

Cygwin

Cygwinは、Unixのような環境を、Windows上で構築させるコマンドラインインターフェースです。

0グッド

0クリップ

投稿2018/06/27 17:23

前提・実現したいこと

指定された探索キー集合から複数の対象キー集合に対して線形探索を行うプログラムを作っています。

前提として同じディレクトリ上にプログラムの他、5000.txt,01000.txt,030000.txt,050000.txtが存在するとしてください。

ソースコードがとても見づらくなってしまいすいません。

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

gccでコンパイルした後
.a/.exe 5000.txt -b 10000 -e 50000 -s 20000
とするとエラーが出てしまいます。
個人的には/対象キー集合ファイルからコア上の対象キー集合への挿入/のfgetsが怪しいと思っています。

Segmentation fault (コアダンプ)

該当のソースコード

c言語

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4 5#define dDefaultBegin (5000) /*対象キーの開始初期値*/ 6#define dDefaultEnd (100000) /*対象キー数の終了初期値*/ 7#define dDefaultStep   (5000) /*対象キー数のステップ幅初期値*/ 8#define dPathSize (64) /*パスを格納する配列サイズ*/ 9#define dKeySize (32) /*キー格納する配列サイズ*/ 10#define dBufferSize (64) /*キーの読み込み時にバッファリングできる配列サイズ*/ 11#define dSearchKeySetSize (50000) /*探索キー集合のキー数*/ 12#define dTargetKeySetSize (100000) /*対象キー集合のキー数*/ 13#define dUsageFormat "Usage: %s SearchKeyFile [-b NUM][-e NUM][-s NUM]\n" 14#define dSearchPatheFormat "/home/key/%s" 15#define dTargetPathFormat "/home/key/%06ld.txt" 16#define dFileOpenErrorMsg "###ERROR: cannot open '%s'\n" 17#define dAllocateErrorMsg "###ERROR: cannot allocate\n" 18#define dOverflowErrorMsg "###ERROR: overflow\n" 19#define dOverflowErrorMsg2 "###ERROR: OVERFLOW\n" 20#define dSuccess (0) /*正常終了*/ 21#define dOptironError (-1) /*エラー終了(コマンドライン引数読み込み失敗)*/ 22#define dFileOpenError (-2) /*エラー終了(ファイル読み込み失敗)*/ 23#define dTrue (!0) 24#define dFalse (0) 25 26typedef struct _OPTION { /*オプションの管理構造体*/ 27 char searchPath[dPathSize]; /*探索キー集合のパス*/ 28 long begin; /*対象キー開始数*/ 29 long end; /*対象キー終了数*/ 30 long step; /*対象キーステップ幅*/ 31}OPTION; 32 33typedef struct _KEYCELL { /*キー単体の形定義*/ 34 char key[dKeySize]; /*キー*/ 35}KEYCELL; 36 37typedef struct _KEYSET { /*探索キー集合の管理構造体*/ 38 KEYCELL table[dSearchKeySetSize]; /*各キーを格納する配列*/ 39 long count; /*キー数*/ 40}KEYSET; 41 42typedef struct _TARGETSET{ /*対象キー集合の管理構造体*/ 43 KEYCELL table[dTargetKeySetSize]; //探索法に応じて設計 44 long count; 45}TARGETSET; 46 47#define CountKeySet(set) ((set)->count) /*管理構造体からキー数の取得*/ 48#define GetKey(set,i) ((set)->table[(i)].key) /*管理構造体からキーの取得*/ 49#define IsReturnCode(c) ((c) == '\n'||(c) == '\r') /*改行文字判定*/ 50 51static int GetOption(OPTION *option, int argc, char *argv[]); 52static char *RemoveReturnCode(char *string); 53KEYSET *InitializeKeySet(void); 54int InsertKeySet(KEYSET *set, const char *key); 55void FinalizeKeySet(KEYSET *set); 56TARGETSET *Initialize(void); 57void Finalize(TARGETSET *set); 58int Insert(TARGETSET *set, const char *key); 59int Search(TARGETSET *set,const char *key); 60 61/* 62概要 メイン関数 63*/ 64int main(int argc, char *argv[]) { 65 OPTION option; /*オプションの管理*/ 66 KEYSET *keySet; /*探索キー集合*/ 67 char path[dPathSize]; /*パスの格納領域*/ 68 char buffer[dBufferSize]; 69 FILE *fp; 70 long num; 71 72 if (GetOption(&option, argc ,argv) == dFalse) /*オプションの解析*/ 73 return dOptironError; 74 75 /* 76 探索キー集合 77 */ 78 if ((fp = fopen(option.searchPath, "rt")) == NULL) { 79 fprintf(stderr, dFileOpenErrorMsg, option.searchPath); 80 return dFileOpenError; 81 } 82 keySet = InitializeKeySet(); /*探索キー集合の初期化*/ 83 /*探索キー集合ファイルからコア上の探索キー集合への挿入*/ 84 while (fgets(buffer, dBufferSize, fp) != NULL) { 85 RemoveReturnCode(buffer); /*改行除去*/ 86 InsertKeySet(keySet, buffer); /*探索キー集合への挿入*/ 87 } 88 fclose(fp); 89 90 /* 91 各対象キー集合 92 */ 93 for (num = option.begin; num <= option.end; num += option.step) { 94 printf("%d\n",num); 95 sprintf(path, dTargetPathFormat, num); /*対象キー集合ファイルのパスの作成*/ 96 if ((fp = fopen(path, "rt")) != NULL) { 97 printf("OK\n"); 98 TARGETSET *targetSet; /*対象キー集合*/ 99 long i; 100 101 targetSet = Initialize(); /*対象キー集合の初期化*/ 102 103 /*対象キー集合ファイルからコア上の対象キー集合への挿入*/ 104 while (fgets(buffer, dBufferSize, fp) != NULL) { 105 RemoveReturnCode(buffer); /*改行除去*/ 106 Insert(targetSet, buffer); /*対象キー集合への挿入*/ 107 } 108 fclose(fp); 109 110 /*探索キー集合の各キーから対象キー集合に対する探索*/ 111 for (i = 0L; i < CountKeySet(keySet); i++) { 112 Search(targetSet, GetKey(keySet, i)); 113 } 114 115 Finalize(targetSet); /*対象キー集合の後処理*/ 116 } 117 } 118 119 FinalizeKeySet(keySet); /*探索キー集合の後処理*/ 120 121 return dSuccess; /*探索キー集合の後処理*/ 122} 123 124/* 125概要 コマンドライン引数を解析して option に探索キー集合のパスや探索範囲などのオプションを設定する 126入力 *option オプション管理構造体(出力)/ argc, argv コマンドライン引数 127出力 dTrue 解析成功/ dFalse 解析失敗 128*/ 129static int GetOption(OPTION *option, int argc, char *argv[]) { 130 char *command; 131 132 command = *argv; 133 option->begin = dDefaultBegin; 134 option->end = dDefaultEnd; 135 option->step = dDefaultStep; 136 137 if (argc < 2) { 138 fprintf(stderr, dUsageFormat, command); 139 return dFalse; 140 } 141 sprintf(option->searchPath, dSearchPatheFormat, *(++argv)); 142 143 while (*(++argv) != NULL) { 144 if (**argv == '-') { 145 while (*(++(*argv)) != '\0') { 146 switch (**argv) { 147 case 'b': /*対象キー開始数*/ 148 if (argv[1] != NULL) option->begin = atol(argv[1]); 149 break; 150 case 'e': /*対象キー終了数*/ 151 if (argv[1] != NULL) option->end = atol(argv[1]); 152 break; 153 case 's': /*対象キーステップ幅*/ 154 if (argv[1] != NULL) option->step = atol(argv[1]); 155 break; 156 default: 157 fprintf(stderr, dUsageFormat, command); 158 return dFalse; 159 } 160 } 161 } 162 } 163 164 return dTrue; 165} 166 167/* 168概要 探索キー集合の管理構造体を作成して初期値を設定する 169入力 なし 170出力 set 作成された探索キー集合の管理構造体 171*/ 172KEYSET *InitializeKeySet(void) { 173 KEYSET *set; 174 175 if ((set = (KEYSET *)malloc(sizeof(KEYSET))) == NULL) { 176 fprintf(stderr, dAllocateErrorMsg); 177 return NULL; 178 } 179 set->count = 0L; /*キー数の初期化*/ 180 181 return set; 182} 183 184/* 185概要 set で管理する探索キー集合に対してキー key を挿入する 186入力 set 管理構造体/ key 挿入するキー 187出力 dTrue 挿入成功/ dFalse 挿入失敗 188*/ 189int InsertKeySet(KEYSET *set, const char *key) { 190 if (set->count >= dSearchKeySetSize) { 191 fprintf(stderr, dOverflowErrorMsg); 192 return dFalse; 193 } 194 strcpy(set->table[set->count++].key, key); 195 196 return dTrue; 197} 198 199/* 200概要 set で管理する探索キー集合を破棄する 201入力 set 管理構造体 202出力 なし 203*/ 204void FinalizeKeySet(KEYSET *set) { 205 free(set); 206} 207 208/* 209概要 文字列 string の改行以降を除去する 210入力 string 対象文字列 211出力 string 改行が除去された対象文字列 212*/ 213static char *RemoveReturnCode(char *string) { 214 char *p; 215 for (p = string; !IsReturnCode(*p) && *p != '\0'; p++) 216 ; 217 *p = '\0'; 218 219 return string; 220} 221 222/*対象キー集合の初期化*/ 223TARGETSET *Initialize(void){ 224 //管理構造体の領域確保など 225 TARGETSET *set; 226 if((set = (TARGETSET *)malloc(sizeof(TARGETSET))) == NULL){ 227 fprintf(stderr,dAllocateErrorMsg); 228 return NULL; 229 } 230 set->count = 0L; 231 232 return set; 233} 234 235/*対象キー集合の後処理*/ 236void Finalize(TARGETSET *set){ 237 //管理構造体の領域解放など 238 free(set); 239} 240 241/*対象キー集合への挿入*/ 242int Insert(TARGETSET *set, const char *key){ 243 244 if(set -> count >=dTargetKeySetSize){ 245 fprintf(stderr,dOverflowErrorMsg2); 246 return dFalse; 247 } 248 strcpy(set->table[set -> count++].key,key); 249 250 return dTrue; 251} 252 253/*対象キー集合に対する探索*/ 254int Search(TARGETSET *set,const char *key){ 255 int i,j; 256 257 258 for(i=0;i<dSearchKeySetSize;i++){ 259 while(set -> table[i].key[j] == *(key + j) && set -> table[i].key[j] != '\0' && *(key + j)!='\0'){ 260 j++; 261 } 262 263 if(set -> table[i].key[j] == *(key + j) == '\0'){ 264 printf("%s\n",key); 265 return dTrue; 266 } 267 } 268 269 return dFalse; 270} 271

試したこと

ここに問題に対して試したことを記載してください。

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答2

0

自己解決

解決しました。
プログラム最後のSearchが間違っていました。
まずは宣言したjの値を宣言し忘れていたため、ゴミ値が入っていました。
またif文での条件を&&で分ける必要がありました。

投稿2018/06/28 08:49

Ghostrick

総合スコア14

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

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

0

C

1KEYSET *InitializeKeySet(void) { 2 KEYSET *set; 3 4 if ((set = (KEYSET *)malloc(sizeof(KEYSET))) == NULL) { 5 fprintf(stderr, dAllocateErrorMsg); 6 return NULL; 7 } 8 set->count = 0L; /*キー数の初期化*/ 9 10 return set; 11}

KEYSET の table を初期化してみてはどうでしょう


でもなさげだなあ、、

気になるところとしては、

#define dKeySize (32) /*キー格納する配列サイズ*/ #define dBufferSize (64) /*キーの読み込み時にバッファリングできる配列サイズ*/

バッファサイズのほうが大きいので、データによってはキーをオーバーして隣を破壊しますね
各Insertで、キーの文字列長をチェックしてみては。

投稿2018/06/27 23:20

編集2018/06/27 23:37
y_waiwai

総合スコア87719

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問