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

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

ただいまの
回答率

88.37%

callocによるエラーについて

解決済

回答 6

投稿

  • 評価
  • クリップ 0
  • VIEW 1,095

Taichi.N_

score 10

前提・実現したいこと

C言語、開発ツールはVisual Studioです。
calloc関数を使ってエラーなく最後まで実行完了したいです。

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

何回目かのcallocによるメモリの確保中に例外がスローされているようだ、というところまではわかりましたが、エラーの詳しい内容がでません。

ConsoleApp.exe によってブレークポイントが発生しました。


とだけ出てしまいます。

該当のソースコード

#include<stdio.h>
#include<stdlib.h>
#define MEMBER 20

typedef struct{
    int year, month, day;
}DATE;

typedef struct person{
    char name[20];
    DATE birthday;
    struct person *next;
}PERSON;

//PERSON *NewData(int ele);
PERSON *NewData(int ele);
void Insert(PERSON*, PERSON*);
void Dele(PERSON*, PERSON);
PERSON *conect(PERSON*, int, PERSON*);
PERSON *MAXB(PERSON *, PERSON *);
void print_list(PERSON *);


int main(void)
{
    FILE *fp;
    char filename[256] = { 0 };
    char buff[256] = { 0 };
    int buf = 0;
    PERSON *p_buf;
    printf("読み込む誕生日リストのファイルを入力してください:");
    scanf("%s", filename);
    if ((fp = fopen(filename, "r")) != NULL)
    {
        while (fgets(buff, 256, fp) != NULL)
        {
            buf++;
        }
        fclose(fp);
        if ((p_buf = NewData(buf)) != NULL)
        {
            buf = 0;
            if ((fp = fopen(filename, "r")) != NULL)
            {
                while (fgets(buff, 256, fp) != NULL)
                {
                    sscanf(buff, "%[^,],%d,%d,%d,\n", &((p_buf + buf)->name), &((p_buf + buf)->birthday.year), &((p_buf + buf)->birthday.month), &((p_buf + buf)->birthday.day));
                    buf++;
                }
                fclose(fp);
                for (size_t i = 0; i < buf; i++)
                {
                    //printf("%s,%d,%d,%d\n", (p_buf + i)->name, (p_buf + i)->birthday.year, (p_buf + i)->birthday.month, (p_buf + i)->birthday.day);
                }
                conect(p_buf, MEMBER, NULL);
                //print_list(conect(p_buf, MEMBER, NULL));
            }
        }

    }

    return 0;
}

PERSON *NewData(int ele)
{
    PERSON *buf;
    buf = calloc(ele, sizeof(PERSON));
    if (buf != NULL)
    {
        return buf;
    }
    else
    {
        return NULL;
    }
}

void Insert(PERSON *before, PERSON *target)
{
    PERSON *buf;
    buf = NewData(1);
    if (buf != NULL)
    {
        if (before != NULL)
        {
            buf = before->next;
            before->next = target;
            target->next = buf;
        }
    }
}

void Dele(PERSON *target, PERSON First)
{
    PERSON *buf;
    buf = &First;
    while (target != buf->next)
    {
        buf = buf->next;
    }
    if (buf != NULL)
    {
        buf->next = target->next;
        free(target);
    }
}
PERSON *conect(PERSON *target, int times, PERSON *p_ANC)
{

    PERSON *p_start;
    p_start = NewData(1);
    if (p_start != NULL)
    {
        for (size_t i = 0; i < times; i++)
        {
            p_start = MAXB(p_start, target + i);
        }
        p_start->next = p_ANC;
        if (times != 1)
        {
            PERSON *Next_T;
            Next_T = NewData(times - 1);
            for (size_t i = 0; i < times; i++)
            {
                if ((target + i) != p_start)
                {
                    *(Next_T + i) = *(target + i);
                }
            }
            return conect(Next_T, times - 1, p_start);
        }
        else
        {
            return p_start;
        }
    }
}
PERSON *MAXB(PERSON *A, PERSON *B)
{
    if (A->birthday.year < B->birthday.year)
    {
        return B;
    }
    else if (A->birthday.year > B->birthday.year)
    {
        return A;
    }
    else
    {
        if (A->birthday.month < B->birthday.month)
        {
            return B;
        }
        else if (A->birthday.month > B->birthday.month)
        {
            return A;
        }
        else
        {
            if (A->birthday.day < B->birthday.day)
            {
                return B;
            }
            else if (A->birthday.day > B->birthday.day)
            {
                return A;
            }
            else
            {
                return A;
            }
        }
    }
}

void print_list(PERSON *start)
{
    if (start != NULL)
    {
        printf("%s,%d,%d,%d\n", start->name, start->birthday.year, start->birthday.month, start->birthday.day);
        print_list(start->next);
    }
}

試したこと

デバッグをして一工程ずつたどってみてcallocのなかで_heap_alloc のところで止まってしまうことは確認しました。

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

Visual Studio 2013,2017で試しました。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 6

+1

sscanf(buff, "%[^,],%d,%d,%d,\n", &((p_buf + buf)->name), &((p_buf + buf)->birthday.year), &((p_buf + buf)->birthday.month), &((p_buf + buf)->birthday.day));

ココんところでコケているよかん。
コメントアウトして実行してみれば

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/01/08 15:32

    その部分でのファイル読み込みは標準出力をしてみたところ正常に読めている様でした。

    キャンセル

  • 2019/01/08 15:36

    そこで表示して正常だったからといって、正常だ、というわけには行かないので、コメントアウトして実行してみる。
    あるいはその行直後で止めて、メモリ内が想定どおりになってるのか見てみれ。

    C言語というのは正常に動作していると見えてその裏ではメモリがぶっ壊されてるというのはふつーに起こる言語です

    キャンセル

  • 2019/01/08 18:57

    ご指摘の個所をコメントアウトしてみました。
    全てのデータが0になった状態で関数内に入りましたが質問時と同じ個所でエラーが起きてしまいました。

    キャンセル

check解決した方法

0

申し訳ございません!どうやら単純に確保したメモリより多く書き込もうとしていたようでした!アドバイスをいただき本当にありがとうございました!

for (size_t i = 0; i < times; i++)
{
     if ((target + i) != p_start)
     {
           *(Next_T + i) = *(target + i);
     }
}


for (size_t j=0,i = 0; i < times; i++)
{
     if ((target + i) != (target+keep))
     {
           *(Next_T + j) = *(target + i);
           j++;
     }

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

その部分でのファイル読み込みは標準出力をしてみたところ正常に読めている様でした。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

こんにちは。

よくわからないバグが出てしまった場合、私は自分で追加した部分を徹底的にコメントアウトして、バグが出なくなる所まで舞い戻るチェック方法を用いています。
面倒なことですが、これが一番かと。。

バグが出なくなる所まで戻せたら、コメントアウトを少しずつ外していって、バグが出る瞬間をとらえてください。
そこがバグの境界線で、原因である可能性がかなり高いと思われますので。

ここじゃないですか?と指摘できるほどのスキルが足りず、申し訳ありません。
がんばってください。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

 buf = calloc(ele, sizeof(PERSON));

      ↓

 buf = (PERSON*)calloc(ele, sizeof(PERSON));


キャストが必要ではないでしょうか。
callocの戻りの型はvoid*となります。
明示的にキャストしないと使えなかったと思います。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/01/08 18:54

    該当箇所を明示的にキャストしてみましたが同じエラーが出てしまいました。

    キャンセル

  • 2019/01/08 19:08

    @ardin さん
    汎用ポインタのキャストが必須なのはCではなくC++では。
    また、Cの場合暗黙のキャストが走りますし、C++の場合そもそもコンパイルエラーを吐くので実行時には影響しないと思います。

    キャンセル

  • 2019/01/09 08:47

    Cでも必要だと思っていましたが、暗黙のキャストOKだったんですね。
    勉強になりました。

    キャンセル

0

すみません。そもそもconectでなにをなさりたいのでしょうか。
conectの引数の意味とその機能を説明していただけませんでしょうか。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/01/08 18:53

    conectでは線形のリストを整列させる機能も持たせているつもりです。
    conect単体では渡された配列の最も最後尾となる要素にの次の要素示すポインタにp_ANCを代入し、最後尾の要素を除いた残りの配列で再起呼び出しをしています。
    *target : 整列対象の配列
    times : リストの要素数
    *p_ANC :整列時の終点要素の次の要素を示すポインタ

    キャンセル

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

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

関連した質問

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