cout出力で?のエラー(初学者)

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
フッフフ

cout出力で?のエラー(初学者)

#1

投稿記事 by フッフフ » 3年前

C++初学者です。初めまして。いきなりですがエラーの原因が特定できないのでここで質問させて下さい。
以下のコード(main.cpp)でVisual Studio Express 2015 windows desktopでデバッグ実行すると良く分からないエラーが出てxstringというファイルが表示されます(このxstringとは一体何なのかも分かっていません)。
デバッグ無し実行するとmain関数の最終行のprintallstudentsまでは問題なく進んでいることが分かるので、
Student::Print();関数でcout出力がうまくいっていないのだろうと大体の予測はつくのですが具体的にどうすればエラーが無くなるのかが分かりません。
どなたか知恵をお貸しください。
ちなみに以下のコードはこのページの下部の問題の解答として僕が書いたコードです。http://ppp-lab.sakura.ne.jp/Programming ... e/011.html

コード:

#include<string>
#include<iostream>

class Student {
	std::string	name;	//名前
	int			grade;	//学年
	int			score;	//得点
public:
	void SetData(std::string str, int grade, int score);
	void Print();
	int getGrade();
};

void Student::SetData(std::string str, int grade, int score) {
	this->name = str;	//ポインタ変数からのメンバ関数の呼び出しにはアローを用いる
	this->grade = grade;
	this->score = score;
}

void Student::Print() {
	std::cout << name <<std::endl;
	std::cout << grade << std::endl;
	std::cout << score << std::endl;
}

int Student::getGrade() {
	return grade;
}

class Teacher {
	std::string	name;
	int			grade;
	int			student_num=0;
	Student* studentsList[40];
public:
	void setData(std::string name, int grade);
	void setStudent(Student* stu_ptr);
	void printAllStudents();
};

void Teacher::setData(std::string name, int grade) {
	this->name = name;
	this->grade = grade;
}

void Teacher::setStudent(Student* stu_ptr) {
	if (stu_ptr->getGrade() == this->grade) {
		std::cout << "生徒追加" << std::endl;
		studentsList[student_num] = stu_ptr;
		student_num++;
	}
	else {
		std::cout << "生徒追加失敗" << std::endl;
	}
}

void Teacher::printAllStudents() {
	for (int i = 0; i < 40; i++) {
		studentsList[i]->Print();
	}

}

int main(void) {
	Student s[2];
	s[0].SetData("Taro", 2, 60);
	s[1].SetData("Hanako", 2, 80);

	Teacher	t;
	t.setData("ひろこ", 2);
	t.setStudent(&s[0]);
	t.setStudent(&s[1]);

	t.printAllStudents();

	return 0;
}

アバター
みけCAT
記事: 6190
登録日時: 8年前
住所: 千葉県
連絡を取る:

Re: cout出力で?のエラー(初学者)

#2

投稿記事 by みけCAT » 3年前

Teacher::printAllStudents関数が間違っていて、未初期化のポインタをデリファレンスしてしまいます。

ループの条件を40未満ではなくstudent_num未満にすると改善するかもしれません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

フッフフ

Re: cout出力で?のエラー(初学者)

#3

投稿記事 by フッフフ » 3年前

みけCAT さんが書きました:Teacher::printAllStudents関数が間違っていて、未初期化のポインタをデリファレンスしてしまいます。

ループの条件を40未満ではなくstudent_num未満にすると改善するかもしれません。
改善しました!ありがとうございます。丁度見落としていたところでした。
初期化されていないポインタの参照が原因だったんですね。
こういう原因の時は具体的にどうおかしいのかコンパイラは教えてくれないのですね。
重ねてありがとうございます。助かりました!

アバター
みけCAT
記事: 6190
登録日時: 8年前
住所: 千葉県
連絡を取る:

Re: cout出力で?のエラー(初学者)

#4

投稿記事 by みけCAT » 3年前

フッフフ さんが書きました:初期化されていないポインタの参照が原因だったんですね。
こういう原因の時は具体的にどうおかしいのかコンパイラは教えてくれないのですね。
デバッガならヒントを与えてくれるかもしれません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

フッフフ

Re: cout出力で?のエラー(初学者)

#5

投稿記事 by フッフフ » 3年前

修正前のプログラムをデバッグ実行したら、画面下部に下のような表示があったのですが、最下行の「アクセス違反」が未初期化のポインタを使ったアクセスによるもの、
という予測の仕方で合っていますか?

'TeacherStudent.exe' (Win32): 'C:\Windows\SysWOW64\cryptbase.dll' が読み込まれました。PDB ファイルを開けないか、ファイルが見つかりません。
'TeacherStudent.exe' (Win32): 'C:\Windows\SysWOW64\sspicli.dll' が読み込まれました。PDB ファイルを開けないか、ファイルが見つかりません。
'TeacherStudent.exe' (Win32): 'C:\Windows\SysWOW64\bcryptprimitives.dll' が読み込まれました。PDB ファイルを開けないか、ファイルが見つかりません。
0x00355D4B で例外がスローされました (TeacherStudent.exe 内): 0xC0000005: 場所 0xCCCCCCE0 の読み取り中にアクセス違反が発生しました

アバター
みけCAT
記事: 6190
登録日時: 8年前
住所: 千葉県
連絡を取る:

Re: cout出力で?のエラー(初学者)

#6

投稿記事 by みけCAT » 3年前

フッフフ さんが書きました:最下行の「アクセス違反」が未初期化のポインタを使ったアクセスによるもの、
という予測の仕方で合っていますか?
今回の場合は、0xCCCCCCCC+αのアドレスがでているので、それであっていますね。

ちなみに、デバッガであるGDBを使うと、落ちた行がわかることがあります。

コード:

YUKI.N> g++ -g3 -Wall -Wextra -std=c++11 -pedantic -static -o raw raw.cpp

YUKI.N> gdb raw
GNU gdb (GDB) 7.6.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from D:\MyData\Documents\programs\_対質問\coutsyuturyokudenoeraa
\raw.exe...done.
(gdb) run
Starting program: D:\MyData\Documents\programs\_ホソ\coutsyuturyokudenoeraa/raw.ex
e
[New Thread 7796.0x814]
生徒追加
生徒追加
Taro
2
60
Hanako
2
80

Program received signal SIGSEGV, Segmentation fault.
0x0045b477 in std::basic_ostream<char, std::char_traits<char> >& std::operator<<
 <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char,
std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::
allocator<char> > const&) ()
(gdb) where
#0  0x0045b477 in std::basic_ostream<char, std::char_traits<char> >& std::operat
or<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<ch
ar, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, s
td::allocator<char> > const&) ()
#1  0x0040142e in Student::Print (this=0xba58c) at raw.cpp:21
#2  0x0040157f in Teacher::printAllStudents (this=0x28fe44) at raw.cpp:59
#3  0x00401720 in main () at raw.cpp:74
(gdb)
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

フッフフ

Re: cout出力で?のエラー(初学者)

#7

投稿記事 by フッフフ » 3年前

GDBですか。必要な時に使ってみようと思います。

YuO
記事: 936
登録日時: 8年前
住所: 東京都世田谷区

Re: cout出力で?のエラー(初学者)

#8

投稿記事 by YuO » 3年前

フッフフ さんが書きました:GDBですか。必要な時に使ってみようと思います。
Visual Studioを使っているのであれば,通常の利用においてGDBが必要になることはありません。

フッフフ さんが書きました:以下のコード(main.cpp)でVisual Studio Express 2015 windows desktopでデバッグ実行すると良く分からないエラーが出てxstringというファイルが表示されます(このxstringとは一体何なのかも分かっていません)。
おそらく,この「良く分からないエラー」とは,恐らく
画像
というダイアログだと思います。これは,
  • アクセス違反などのCPU例外 (だいたいはエラー)
  • throwされたがcatchされていないC++の例外
があったことを通知するダイアログになります。
このダイアログは,デバッグの起点になります。

ここで[中断]を押して,メニューの[デバッグ] - [ウィンドウ] - [呼び出し履歴]を選択します。
そうすると,[呼び出し履歴]のペインが開きます。
画像
履歴を上から見ていって,自分のコードを探します。今回だと,上から3行目が該当行です。
その行をダブルクリックします。
その上で,利用している変数 (ここではname) にマウスカーソルを合わせます。
画像
nameのsizeなどがおかしいことがわかります。
次に,もう一回,呼び出し履歴を遡ります。
画像
iの値が2です。さらに,マウスカーソルをstudentsListに合わせると,
画像
studentsListは0と1だけが設定されています。
つまり,2にはオブジェクトが割り当てられていないために,今回はエラーになっていることがわかります。

なお,イメージのキャプチャはVisual Studio Community 2015ですが,Visual Studio Express 2015でも同じ操作で同じことができます。


ちなみに,Visual C++のコンパイラは,Debug構成においては,default-initialization時にPOD型の各バイトに0xCCを設定します。
ポインタ型でこのバイト構成を見つけると,IDEはそのポインタは不正である,という取り扱いをしてくれます。
オフトピック
VC++使うなら,0xCCが全バイトに設定されたオブジェクトは「怪しい」と思った方がよい
みけCAT さんが書きました:ちなみに、デバッガであるGDBを使うと、落ちた行がわかることがあります。
Visual Studio ExpressでもGDBでのデバッグが可能なのでしょうか。
Visual Studio Community/Professional以上では,Visual C++ for IoT Development拡張で可能なようですが。
そもそも,今回,GCC+GDBを持ち出す意味はないと思いますけどね。

フッフフ

Re: cout出力で?のエラー(初学者)

#9

投稿記事 by フッフフ » 3年前

>>YuOさん
スクショ付きの分かりやすい解説ありがとうございます。物凄く頭が下がります。
よく分からないエラーというのはそれです。
VSにこんな便利な機能があったなんて・・
順を追って真似してみたらどんな風にすればデバッグができるのか大体分かりました。
0xCC...という値もヒントになるのですね。

閉鎖

“C言語何でも質問掲示板” へ戻る