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

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

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

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

6回答

3651閲覧

callocによるエラーについて

Taichi.N_

総合スコア10

C

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

0クリップ

投稿2019/01/08 06:12

前提・実現したいこと

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

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

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

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

とだけ出てしまいます。

該当のソースコード

C

1#include<stdio.h> 2#include<stdlib.h> 3#define MEMBER 20 4 5typedef struct{ 6 int year, month, day; 7}DATE; 8 9typedef struct person{ 10 char name[20]; 11 DATE birthday; 12 struct person *next; 13}PERSON; 14 15//PERSON *NewData(int ele); 16PERSON *NewData(int ele); 17void Insert(PERSON*, PERSON*); 18void Dele(PERSON*, PERSON); 19PERSON *conect(PERSON*, int, PERSON*); 20PERSON *MAXB(PERSON *, PERSON *); 21void print_list(PERSON *); 22 23 24int main(void) 25{ 26 FILE *fp; 27 char filename[256] = { 0 }; 28 char buff[256] = { 0 }; 29 int buf = 0; 30 PERSON *p_buf; 31 printf("読み込む誕生日リストのファイルを入力してください:"); 32 scanf("%s", filename); 33 if ((fp = fopen(filename, "r")) != NULL) 34 { 35 while (fgets(buff, 256, fp) != NULL) 36 { 37 buf++; 38 } 39 fclose(fp); 40 if ((p_buf = NewData(buf)) != NULL) 41 { 42 buf = 0; 43 if ((fp = fopen(filename, "r")) != NULL) 44 { 45 while (fgets(buff, 256, fp) != NULL) 46 { 47 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)); 48 buf++; 49 } 50 fclose(fp); 51 for (size_t i = 0; i < buf; i++) 52 { 53 //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); 54 } 55 conect(p_buf, MEMBER, NULL); 56 //print_list(conect(p_buf, MEMBER, NULL)); 57 } 58 } 59 60 } 61 62 return 0; 63} 64 65PERSON *NewData(int ele) 66{ 67 PERSON *buf; 68 buf = calloc(ele, sizeof(PERSON)); 69 if (buf != NULL) 70 { 71 return buf; 72 } 73 else 74 { 75 return NULL; 76 } 77} 78 79void Insert(PERSON *before, PERSON *target) 80{ 81 PERSON *buf; 82 buf = NewData(1); 83 if (buf != NULL) 84 { 85 if (before != NULL) 86 { 87 buf = before->next; 88 before->next = target; 89 target->next = buf; 90 } 91 } 92} 93 94void Dele(PERSON *target, PERSON First) 95{ 96 PERSON *buf; 97 buf = &First; 98 while (target != buf->next) 99 { 100 buf = buf->next; 101 } 102 if (buf != NULL) 103 { 104 buf->next = target->next; 105 free(target); 106 } 107} 108PERSON *conect(PERSON *target, int times, PERSON *p_ANC) 109{ 110 111 PERSON *p_start; 112 p_start = NewData(1); 113 if (p_start != NULL) 114 { 115 for (size_t i = 0; i < times; i++) 116 { 117 p_start = MAXB(p_start, target + i); 118 } 119 p_start->next = p_ANC; 120 if (times != 1) 121 { 122 PERSON *Next_T; 123 Next_T = NewData(times - 1); 124 for (size_t i = 0; i < times; i++) 125 { 126 if ((target + i) != p_start) 127 { 128 *(Next_T + i) = *(target + i); 129 } 130 } 131 return conect(Next_T, times - 1, p_start); 132 } 133 else 134 { 135 return p_start; 136 } 137 } 138} 139PERSON *MAXB(PERSON *A, PERSON *B) 140{ 141 if (A->birthday.year < B->birthday.year) 142 { 143 return B; 144 } 145 else if (A->birthday.year > B->birthday.year) 146 { 147 return A; 148 } 149 else 150 { 151 if (A->birthday.month < B->birthday.month) 152 { 153 return B; 154 } 155 else if (A->birthday.month > B->birthday.month) 156 { 157 return A; 158 } 159 else 160 { 161 if (A->birthday.day < B->birthday.day) 162 { 163 return B; 164 } 165 else if (A->birthday.day > B->birthday.day) 166 { 167 return A; 168 } 169 else 170 { 171 return A; 172 } 173 } 174 } 175} 176 177void print_list(PERSON *start) 178{ 179 if (start != NULL) 180 { 181 printf("%s,%d,%d,%d\n", start->name, start->birthday.year, start->birthday.month, start->birthday.day); 182 print_list(start->next); 183 } 184}

試したこと

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

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

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

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

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

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

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

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

guest

回答6

0

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 06:29

y_waiwai

総合スコア87774

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

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

Taichi.N_

2019/01/08 06:32

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

2019/01/08 06:36

そこで表示して正常だったからといって、正常だ、というわけには行かないので、コメントアウトして実行してみる。 あるいはその行直後で止めて、メモリ内が想定どおりになってるのか見てみれ。 C言語というのは正常に動作していると見えてその裏ではメモリがぶっ壊されてるというのはふつーに起こる言語です
Taichi.N_

2019/01/08 09:57

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

0

自己解決

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

C

1for (size_t i = 0; i < times; i++) 2{ 3 if ((target + i) != p_start) 4 { 5 *(Next_T + i) = *(target + i); 6 } 7}

C

1for (size_t j=0,i = 0; i < times; i++) 2{ 3 if ((target + i) != (target+keep)) 4 { 5 *(Next_T + j) = *(target + i); 6 j++; 7 }

投稿2019/01/08 10:19

Taichi.N_

総合スコア10

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

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

0

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

投稿2019/01/08 09:29

tatsu99

総合スコア5438

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

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

Taichi.N_

2019/01/08 09:53

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

0

C

1 buf = calloc(ele, sizeof(PERSON)); 2 3      ↓ 4 5 buf = (PERSON*)calloc(ele, sizeof(PERSON)); 6

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

投稿2019/01/08 08:01

編集2019/01/08 08:05
ardin

総合スコア544

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

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

Taichi.N_

2019/01/08 09:54

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

2019/01/08 10:08

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

2019/01/08 23:47

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

0

こんにちは。

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

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

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

投稿2019/01/08 06:53

poniponiponiki

総合スコア98

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

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

0

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

投稿2019/01/08 06:32

Taichi.N_

総合スコア10

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問