[解決済み】C++ Exception thrown: read access violation.これはnullptrでした。
質問
プログラミングの授業で、講師が自ら作成したストレステストを実行できるプログラムを設計することが要求されています。
私たちはノードとリンクリストを扱っていますが、このテーマについて私が見たどのYouTubeのビデオとも異なる方法で取り組んでいます。
ここ2、3日、自分のプログラムのどこがおかしいのか、髪をかきむしりながら考えているのですが、なかなかうまくいきません。
以下は、私のNode.cppファイルのコードです(Node.hをインクルードしていません)。
#include "Node.h"
Node::Node() {
m_value = 0;
m_next = nullptr;
}
void Node::setValue(int val) {
m_value = val;
}
int Node::getValue() const {
return m_value;
}
void Node::setNext(Node* prev) {
m_next = prev;
}
Node* Node::getNext() const {
return m_next;
}
以下は私のLinkedList.cppです。
#include <iostream>
#include <vector>
#include "LinkedList.h"
LinkedList::LinkedList() {
m_front = nullptr;
m_size = 0;
}
LinkedList::~LinkedList() {
// Deconstructor
m_size = 0;
Node* a = m_front;
Node* b = a->getNext();
while (a->getNext() != NULL) {
delete a;
a = b;
b = b->getNext();
}
delete a;
a = NULL;
}
bool LinkedList::isEmpty() const{
if (m_size == 0) {
return true;
}
else {
return false;
}
}
int LinkedList::size() const {
return m_size;
}
bool LinkedList::search(int value) const {
if (m_size == 0) {
return false;
}
else if (m_size == 1) {
if (m_front->getValue() == value) {
return true;
}
else {
return false;
}
}
else {
Node* a = m_front;
for (int i = 0; i < m_size; i++) {
if (a->getValue() == value) {
return true;
}
else {
a = a->getNext();
}
}
return false;
}
}
void LinkedList::printList() const {
std::cout << "List: ";
if (m_size == 0) {
// Print Nothing
}
else if (m_size == 1) {
std::cout << m_front->getValue();
}
else {
Node* a = new Node();
a = m_front;
int b = m_front->getValue();
std::cout << b << ", ";
while (a->getNext() != NULL) {
a = a->getNext();
if (a->getNext() == NULL) {
std::cout << a->getValue();
}
else {
std::cout << a->getValue() << ", ";
}
}
}
std::cout << std::endl;
}
void LinkedList::addBack(int value) {
Node* a = new Node();
a->setValue(value);
if (m_size == 0) {
m_front = a;
}
else {
Node* b = new Node();
b = m_front;
while (b->getNext() != NULL) {
b = b->getNext();
}
b->setNext(a);
}
m_size++;
}
void LinkedList::addFront(int value) {
Node* a = new Node(); // Check later
a->setNext(m_front);
a->setValue(value);
m_front = a;
m_size++;
}
bool LinkedList::removeBack() {
if (m_size == 0) {
return false;
}
else {
Node* a = new Node();
Node* b = new Node();
a = m_front;
while (a->getNext() != NULL) {
b = a;
a = a->getNext();
}
b->setNext(nullptr);
delete a;
a = NULL;
m_size--;
return true;
}
}
bool LinkedList::removeFront() {
if (m_size == 0) {
return false;
}
else {
Node* a = new Node();
a = m_front;
m_front = m_front->getNext();
delete a;
a = NULL;
m_size--;
return true;
}
}
std::vector<int> LinkedList::toVector() const {
if (m_size == 0) {
std::vector<int> b;
return b;
}
else {
std::vector<int> a(m_size);
Node* b = new Node();
b = m_front;
for (int i = 0; i < m_size; i++) {
a[i] = b->getValue();
b = b->getNext();
}
return a;
}
}
基本的に、私は自分でプログラムをテストして、リンクリストを作り、すべての追加と削除の関数を実行し、リストをうまく印刷することができました。問題は、講師が出したテストを実行したところ、以下のように表示され、問題が発生しました(これらの印刷メッセージは別のファイルにありますが、これらは渡された文字列引数を印刷しているようにしか見えません)。
int score = 0;
const int MAX_SCORE = 90;
std::cerr << "\n\n=========================\n";
std::cerr << " RUNNING TEST SUITE \n";
std::cerr << "=========================\n\n";
//Run test and award points where appropriate
score += test1() ? 2 : 0;
score += test2() ? 2 : 0;
score += test3() ? 3 : 0;
このテストは18回行われますが、私のプログラムは決して最初のテストを通過することができません。最初のテストに合格すると、突然エラーを投げます。
bool Test_LinkedList::test1()
{
LinkedList list;
bool isPassed = false;
printTestMessage("size of empty list is zero");
isPassed = list.size() == 0;
printPassFail(isPassed);
return (isPassed);
}
実際にクラッシュする前に、このような出力が得られました。
=========================
RUNNING TEST SUITE
=========================
Test 1: size of empty list is zero: PASSED
つまり、最初のテストはパスするものの、そこから先には進めないということです。どういうことかというと、次のようなcoutメッセージを投げてみたのです。
score += test1() ? 2 : 0;
std::cout << "Done with test 1"
score += test2() ? 2 : 0;
score += test3() ? 3 : 0;
しかし、それが出力されることはない。代わりに、私のプログラムは壊れ、Visual Studioは次のようなメッセージをポップアップ表示します。
Exception thrown: read access violation.
this was nullptr.
If there is a handler for this exception, the program may be safely continued.
そして、Node.cppにある私のメソッドを指し示します。
Node* Node::getNext() const {
return m_next;
}
すみません、読み切れないほどの文章ですが、今、困っているのを通り越して、明日の早朝が締め切りなので、オフィスアワーに行く時間がないのです。
edit: 最初のテストを省いて実行してみました。次の6つのテストは通過しましたが、7つ目(8つ目)で全く同じエラーで失敗します。
bool Test_LinkedList::test8()
{
LinkedList list;
bool isPassed = false;
printTestMessage("search returns false on empty list");
isPassed = !list.search(42);
printPassFail(isPassed);
return (isPassed);
}
解決方法は?
その
LinkedList
デストラクタにはいくつかの問題があります。まず
m_size
から
0
と
a
から
NULL
というのも、デストラクタが終了した時点で両方とも消えてしまうからです。さらに重要なことは、リストが空のとき、コードはヌルポインタを参照解除しようとすることです。
Node* a = m_front; // okay, gets that head pointer
Node* b = a->getNext(); // bang!!
もっとすっきりした書き方はこちらです。
Node* a = m_front;
while (a != NULL) {
Node *temp = a->getNext();
delete a;
a = temp;
}
関連
-
[解決済み】C++ クラスヘッダが含まれているときに「不明な型」があるのはなぜですか?重複
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み】'cout'は型名ではない
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み] 既に.objで定義されている-二重包含はない
-
[解決済み】エラー。switchステートメントでcaseラベルにジャンプする
-
[解決済み] 式はクラス型を持つ必要があります。
-
[解決済み】リンカーエラーです。"リンカ入力ファイルはリンクが行われていないため未使用"、そのファイル内の関数への未定義参照
-
[解決済み] 非静的データメンバの無効な使用
-
[解決済み] 警告:暗黙の定数変換でのオーバーフロー
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン