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

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

ただいまの
回答率

90.32%

  • Cygwin

    73questions

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

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

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 453

Ghostrick

score 4

 前提・実現したいこと

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

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

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

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

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

Segmentation fault (コアダンプ)

 該当のソースコード

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define dDefaultBegin       (5000)    /*対象キーの開始初期値*/
#define dDefaultEnd        (100000)    /*対象キー数の終了初期値*/
#define dDefaultStep      (5000)        /*対象キー数のステップ幅初期値*/
#define dPathSize        (64)        /*パスを格納する配列サイズ*/
#define    dKeySize        (32)        /*キー格納する配列サイズ*/
#define    dBufferSize        (64)        /*キーの読み込み時にバッファリングできる配列サイズ*/
#define    dSearchKeySetSize    (50000)        /*探索キー集合のキー数*/
#define dTargetKeySetSize    (100000)    /*対象キー集合のキー数*/
#define dUsageFormat        "Usage: %s SearchKeyFile [-b NUM][-e NUM][-s NUM]\n"
#define dSearchPatheFormat    "/home/key/%s"
#define dTargetPathFormat    "/home/key/%06ld.txt"
#define dFileOpenErrorMsg    "###ERROR: cannot open '%s'\n"
#define dAllocateErrorMsg    "###ERROR: cannot allocate\n"
#define dOverflowErrorMsg    "###ERROR: overflow\n"
#define dOverflowErrorMsg2    "###ERROR: OVERFLOW\n"
#define dSuccess        (0)        /*正常終了*/
#define    dOptironError        (-1)        /*エラー終了(コマンドライン引数読み込み失敗)*/
#define dFileOpenError        (-2)        /*エラー終了(ファイル読み込み失敗)*/
#define    dTrue            (!0)        
#define    dFalse            (0)

typedef struct _OPTION {            /*オプションの管理構造体*/
    char    searchPath[dPathSize];        /*探索キー集合のパス*/
    long    begin;                /*対象キー開始数*/
    long    end;                /*対象キー終了数*/
    long    step;                /*対象キーステップ幅*/
}OPTION;

typedef struct _KEYCELL {            /*キー単体の形定義*/
    char    key[dKeySize];            /*キー*/
}KEYCELL;

typedef struct _KEYSET {            /*探索キー集合の管理構造体*/
    KEYCELL    table[dSearchKeySetSize];    /*各キーを格納する配列*/
    long    count;                /*キー数*/
}KEYSET;

typedef struct _TARGETSET{            /*対象キー集合の管理構造体*/
    KEYCELL    table[dTargetKeySetSize];    //探索法に応じて設計
    long    count;
}TARGETSET;

#define    CountKeySet(set)    ((set)->count)                    /*管理構造体からキー数の取得*/
#define    GetKey(set,i)        ((set)->table[(i)].key)            /*管理構造体からキーの取得*/
#define IsReturnCode(c)        ((c) == '\n'||(c) == '\r')        /*改行文字判定*/

static int GetOption(OPTION *option, int argc, char *argv[]);
static char *RemoveReturnCode(char *string);
KEYSET *InitializeKeySet(void);
int InsertKeySet(KEYSET *set, const char *key);
void FinalizeKeySet(KEYSET *set);
TARGETSET *Initialize(void);
void Finalize(TARGETSET *set);
int Insert(TARGETSET *set, const char *key);
int Search(TARGETSET *set,const char *key);

/*
概要        メイン関数
*/
int main(int argc, char *argv[]) {
    OPTION option;                /*オプションの管理*/
    KEYSET *keySet;                /*探索キー集合*/
    char path[dPathSize];        /*パスの格納領域*/
    char buffer[dBufferSize];
    FILE *fp;
    long num;

    if (GetOption(&option, argc ,argv) == dFalse)        /*オプションの解析*/
        return dOptironError;

    /*
    探索キー集合
    */
    if ((fp = fopen(option.searchPath, "rt")) == NULL) {
        fprintf(stderr, dFileOpenErrorMsg, option.searchPath);
        return dFileOpenError;
    }
    keySet = InitializeKeySet();                            /*探索キー集合の初期化*/
    /*探索キー集合ファイルからコア上の探索キー集合への挿入*/
    while (fgets(buffer, dBufferSize, fp) != NULL) {
        RemoveReturnCode(buffer);                    /*改行除去*/
        InsertKeySet(keySet, buffer);                /*探索キー集合への挿入*/
    }
    fclose(fp);

    /*
    各対象キー集合
    */
    for (num = option.begin; num <= option.end; num += option.step) {
        printf("%d\n",num);
        sprintf(path, dTargetPathFormat, num);        /*対象キー集合ファイルのパスの作成*/
        if ((fp = fopen(path, "rt")) != NULL) {
            printf("OK\n");
            TARGETSET *targetSet;            /*対象キー集合*/
            long i;

            targetSet = Initialize();        /*対象キー集合の初期化*/

            /*対象キー集合ファイルからコア上の対象キー集合への挿入*/
            while (fgets(buffer, dBufferSize, fp) != NULL) {
                RemoveReturnCode(buffer);    /*改行除去*/
                Insert(targetSet, buffer);    /*対象キー集合への挿入*/
            }
            fclose(fp);

            /*探索キー集合の各キーから対象キー集合に対する探索*/
            for (i = 0L; i < CountKeySet(keySet); i++) {
                Search(targetSet, GetKey(keySet, i));
            }

            Finalize(targetSet);            /*対象キー集合の後処理*/
        }
    }

    FinalizeKeySet(keySet);                    /*探索キー集合の後処理*/

    return dSuccess;                    /*探索キー集合の後処理*/
}

/*
概要    コマンドライン引数を解析して option に探索キー集合のパスや探索範囲などのオプションを設定する
入力    *option オプション管理構造体(出力)/ argc, argv コマンドライン引数
出力    dTrue 解析成功/ dFalse 解析失敗
*/
static int GetOption(OPTION *option, int argc, char *argv[]) {
    char *command;

    command = *argv;
    option->begin = dDefaultBegin;
    option->end = dDefaultEnd;
    option->step = dDefaultStep;

    if (argc < 2) {
        fprintf(stderr, dUsageFormat, command);
        return dFalse;
    }
    sprintf(option->searchPath, dSearchPatheFormat, *(++argv));

    while (*(++argv) != NULL) {
        if (**argv == '-') {
            while (*(++(*argv)) != '\0') {
                switch (**argv) {
                case 'b':    /*対象キー開始数*/
                    if (argv[1] != NULL) option->begin = atol(argv[1]);
                    break;
                case 'e':    /*対象キー終了数*/
                    if (argv[1] != NULL) option->end = atol(argv[1]);
                    break;
                case 's':    /*対象キーステップ幅*/
                    if (argv[1] != NULL) option->step = atol(argv[1]);
                    break;
                default:
                    fprintf(stderr, dUsageFormat, command);
                    return dFalse;
                }
            }
        }
    }

    return dTrue;
}

/*
概要    探索キー集合の管理構造体を作成して初期値を設定する
入力    なし
出力    set 作成された探索キー集合の管理構造体
*/
KEYSET *InitializeKeySet(void) {
    KEYSET *set;

    if ((set = (KEYSET *)malloc(sizeof(KEYSET))) == NULL) {
        fprintf(stderr, dAllocateErrorMsg);
        return NULL;
    }
    set->count = 0L;        /*キー数の初期化*/

    return set;
}

/*
概要    set で管理する探索キー集合に対してキー key を挿入する
入力    set 管理構造体/ key 挿入するキー
出力    dTrue 挿入成功/ dFalse 挿入失敗
*/
int InsertKeySet(KEYSET *set, const char *key) {
    if (set->count >= dSearchKeySetSize) {
        fprintf(stderr, dOverflowErrorMsg);
        return dFalse;
    }
    strcpy(set->table[set->count++].key, key);

    return dTrue;
}

/*
概要    set で管理する探索キー集合を破棄する
入力    set 管理構造体
出力    なし
*/
void FinalizeKeySet(KEYSET *set) {
    free(set);
}

/*
概要    文字列 string の改行以降を除去する
入力    string 対象文字列
出力    string 改行が除去された対象文字列
*/
static char *RemoveReturnCode(char *string) {
    char *p;
    for (p = string; !IsReturnCode(*p) && *p != '\0'; p++)
        ;
    *p = '\0';

    return string;
}

/*対象キー集合の初期化*/
TARGETSET *Initialize(void){
    //管理構造体の領域確保など
    TARGETSET *set;
    if((set = (TARGETSET *)malloc(sizeof(TARGETSET))) == NULL){
        fprintf(stderr,dAllocateErrorMsg);
        return NULL;
    }
    set->count = 0L;

    return set;
}

/*対象キー集合の後処理*/
void Finalize(TARGETSET *set){
    //管理構造体の領域解放など
    free(set);
}

/*対象キー集合への挿入*/
int Insert(TARGETSET *set, const char *key){

    if(set -> count >=dTargetKeySetSize){
        fprintf(stderr,dOverflowErrorMsg2);
        return dFalse;
    }
    strcpy(set->table[set -> count++].key,key);

    return dTrue;
}

/*対象キー集合に対する探索*/
int Search(TARGETSET *set,const char *key){
    int i,j;


    for(i=0;i<dSearchKeySetSize;i++){
        while(set -> table[i].key[j] == *(key + j) && set -> table[i].key[j] != '\0' && *(key + j)!='\0'){
            j++;
        }

        if(set -> table[i].key[j] == *(key + j) == '\0'){
            printf("%s\n",key);
            return dTrue;
        }    
    }

    return dFalse;
}

 試したこと

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

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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

check解決した方法

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

KEYSET *InitializeKeySet(void) {
    KEYSET *set;

    if ((set = (KEYSET *)malloc(sizeof(KEYSET))) == NULL) {
        fprintf(stderr, dAllocateErrorMsg);
        return NULL;
    }
    set->count = 0L;        /*キー数の初期化*/

    return set;
}


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


でもなさげだなあ、、

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

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


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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.32%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Cygwin

    73questions

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