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

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

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

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

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

Null

Nullとは、プログラミング言語やデータベースにおけるデータ表現の一種です。コンテキストによって"空"もしくは"長さ0の文字列"、”未知・不明”を意味します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

3600閲覧

c++におけるmallocのNULLポインターの逆参照

ttz

総合スコア1

C

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

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

Null

Nullとは、プログラミング言語やデータベースにおけるデータ表現の一種です。コンテキストによって"空"もしくは"長さ0の文字列"、”未知・不明”を意味します。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/10/15 03:38

編集2020/10/15 04:44

前提・実現したいこと

C++にて、新たな会員をリスト末尾に追加するプログラムを書いています。
提示されたプログラムの穴埋めをする方式で書いているので自分で変更できる箇所は限られています。(コード内で穴埋め箇所をコメントしました)
コンパイル時にエラーは見つかりませんでしたが、以下の警告が出ました。また、実行するとmain関数while文でエラーが出てプログラムが停止します(関数createMember、関数addを除いたwhile文だと実行できたため、警告が出た関数createMemberに問題があると考えています)。

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

NULLポインター"m"を逆参照しています。 m->nameは0である可能性があります。この動作は、関数'strcpy'の指定に従っていません。

該当のソースコード

C++

1#define _CRT_SECURE_NO_WARNINGS /*自分のパソコンの環境上必要なため*/ 2#include <stdio.h> 3#include <stdlib.h> 4#include <string.h> 5 6typedef struct MEMBER { 7 char* name; 8 int point; 9 struct MEMBER* next; /*構造体のメンバはすべて穴埋め。名前、ポイント、次の要素へのポインタが必要*/ 10} Member; 11 12Member* top; 13 14Member* createMember(char* name, int pt) 15{ 16 Member* m = (Member*)malloc(sizeof(Member)); /*sizeof(Member)が穴埋め*/ 17 m->name = (char*)malloc(sizeof(char) + 1); /*sizeof(char)が穴埋め。この行でエラー「NULLポインタ~」が発生*/ 18 strcpy(m->name, name); /*この行でエラー「m->nameは~」が発生*/ 19 m->point = pt; 20 m->next = NULL; 21 return m; 22} 23 24void FreeMember(Member* m) 25{ 26 free(m->name); 27 free(m); 28} 29 30void add(Member* m) 31{ 32 if (top == NULL) 33 top = m; 34 else 35 { 36 Member* cur = top; 37 while (cur->next != NULL) 38 { 39 cur = cur->next; 40 } 41 cur->next = m; /*else文内は全て穴埋め。最後尾に新たな会員mを追加する*/ 42 } 43} 44 45void printList(void) 46{ 47 Member* p = top; 48 for (int i = 1;p;p = p->next, i++) 49 { 50 printf("%d:%s[%d]", i, p->name, p->point); 51 if (p->next) 52 printf(" -> "); 53 } 54 printf("\n"); 55} 56 57int main(void) 58{ 59 FILE* fp = fopen("members.txt", "r"); /*memberx.txtはプログラムと同じソースファイル内に存在し、名前とポイント数が記載されています*/ 60 char buf[100]; 61 while(fgets(buf,100,fp)) 62 { 63 char* name = strtok(buf, "\t\n"); 64 int pt = atoi(strtok(NULL, "\t\n")); 65 Member* m = createMember(name, pt); /*(name,pt)が穴埋め*/ 66 add(m); /*mが穴埋め*/ 67 } 68 fclose(fp); 69 printList(); 70} 71/*以下、members.txtのコピペ 72Watson 1850 73Greg 1320 74Fald 990 75Tiger 2500 76George 3350 77Nick 1080 78Daily 704 79Aoki 834 80Jambo 910 81Kuramoto 520 82*/ 83

試したこと

sizeof(Member)をsizeof(Member)*10へ変更
関数createMembr、addをmain関数から消しての動作確認

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

Visual studio2019 (質問前日に最新版へ更新済み、更新後も同様のエラーの発生を確認)

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

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

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

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

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

ozwk

2020/10/15 04:22 編集

* 警告とエラーは異なるものです * strtokのところは両方とも本当に"\t\n"ですか? * members.txtを見せてください。長い場合は数行でいいです、特に区切り文字がちゃんとタブ文字になっているかを見たいです
ttz

2020/10/15 04:33

コメントありがとうございます。 警告とエラーが異なることは理解しています。strtokの箇所は2つとも\t\nで、members.txtは以下の通りです(コピペしたものです) Watson 1850 Greg 1320 Fald 990 Tiger 2500 George 3350 Nick 1080 Daily 704 Aoki 834 Jambo 910 Kuramoto 520
ttz

2020/10/15 04:40

一応ソースコード内にもコピペしておきます。
guest

回答3

0

ベストアンサー

コンパイル時の警告に関してですが、

C

1 Member* m = (Member*)malloc(sizeof(Member)); 2 m->name = (char*)malloc(sizeof(char) + 1);

malloc関数のエラー判定がないので、mallocからエラーリターン(nullポインタ)したときに
m->nameはnullポインタ参照になっちゃうよ!
ってコンパイラが注意したってことでしょうね。
まあ、穴埋め外のとこだし、メモリ使い切りしない限り発生しないから端折ったんでしょうね。
(学習用の課題としてどうかと思いますが。。。)

実行時の問題については、y_waiwaiさんcateyeさんの回答で回避できると思います。

投稿2020/10/15 04:54

DreamTheater

総合スコア1095

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

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

ttz

2020/10/15 05:14

ご指摘の通りエラー判定を追加したところ警告文は消えました。ありがとうございます。
guest

0

たぶんこう↓

c

1 Member* m = (Member*)malloc(sizeof(Member)); /*sizeof(Member)が穴埋め*/ 2 size_t len = strlen(name); 3 m->name = (char*)malloc(len + 1); /*sizeof(char)+1が穴埋め。この行でエラー「NULLポインタ~」が発生*/ 4

あと、malloc()は,復帰値のエラーチェックを・・・
[追記]

c

1Member* m = (Member*)malloc(sizeof(Member)); 2if(m != NULL){ 3 m->name = (char*)malloc(strlen(name) + 1); 4}else{ 5 return NULL; 6}

・・・としても、警告に成りますか?

投稿2020/10/15 03:54

編集2020/10/15 05:13
cateye

総合スコア6851

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

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

cateye

2020/10/15 03:56

穴埋めなら m->name = (char*)malloc(strlen(name)+ 1);
ttz

2020/10/15 04:36

ありがとうございます。 2つとも実際に確認させていただきましたが、質問内容と同じ警告が出てしまいました...
ttz

2020/10/15 05:12

すみません、mallocの復帰値についてのご指摘があったのを忘れていました。 m、m->name両方についてNULLポインターだった場合の処理を追加したところ警告文自体は消えました。ありがとうございます。
guest

0

m->name = (char*)malloc(sizeof(char) + 1);

これ、2バイトしか確保してませんが、そんでいいんでしょうか

投稿2020/10/15 03:41

y_waiwai

総合スコア87774

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

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

ttz

2020/10/15 03:49

すみません、ミスがありました。 該当の行についてですが、穴埋めとなっていたのはsizeof(char)のみで、+1は提示された穴埋めプログラムに元々書かれていました。
y_waiwai

2020/10/15 04:21

なんかの課題か宿題でしょうか
ttz

2020/10/15 04:38

大学の課題です。 穴埋め箇所に入れた文と実行結果をレポートに書くことになっているので、基本的には穴埋め箇所以外は変更なしで完成させないといけないようになっています。
y_waiwai

2020/10/15 04:40

ならまずは、コードが何をしているのか理解することからはじめましょう。 アテズッポでコード書いてもどにもなりません
ttz

2020/10/15 04:48

malloc関数については学習済みのため(mallocを使用したプログラムもいくつか書いています)自分ではある程度理解しているつもりでしたが、もし他の方から見て理解度が足りないようでしたら申し訳ありません。 また、この質問を閲覧してくださった方に誤解されないよう訂正させていただきますが、自分は当てずっぽうでこのプログラムの穴埋めを行っているわけではありません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問