1. ホーム
  2. c++

[解決済み】C++: アクセス違反の書き込み場所

2022-02-12 18:53:21

質問

使用しています。MSVS2012

コード

elemalg.h

#include <vector>
#include <string>
#include <fstream>

class ElemAlg
{
private:
std::string difficultlyLevel, question, answerToRead;
std::vector<std::string> questions, answers;

std::vector<std::string> GetQuiz(int);
};

elemalg.cpp

#include "elemalg.h"

std::vector<std::string> ElemAlg::GetQuiz(int difficulty)
{
if (difficulty == 1) { difficultyLevel = "algE"; }
if (difficulty == 2) { difficultyLevel = "algM"; }  
if (difficulty == 3) { difficultyLevel = "algH"; }
if (difficulty == 4) { difficultyLevel = "algVH"; }

std::ifstream fin(difficultyLevel + ".txt");
while (std::getline(fin, question)) { questions.push_back(question); }
fin.close();

std::ifstream fin2(difficultyLevel + "Answers.txt");
while (std::getline(fin2, answerToRead))    { answers.push_back(answerToRead); }
fin2.close();

return questions;
}

MathTutor.cpp

#includes etc
ElemAlg *ea;
ea->GetQuiz(1);

GetQuiz は間違いなく 1 から 4 までの整数が渡され、これはメソッドが呼ばれる前に検証されます。

difficultyLevel はヘッダーファイルで定義された文字列です。

コンパイラは、最初の if 関数を使用します。

を削除すると if 関数を定義し difficultyLevel をalgEとして、同じ問題をテストするためだけです。

を削除すると difficultyLevel としてファイルを開きます。 "algE.txt""algEAnswers" を実行すると、同じ問題が発生しますが、コードがwhileループに入ると、別のメモリ位置に発生します。

解決方法は?

あなたの悩みはここにあります。

ElemAlg *ea;
ea->GetQuiz(1);

のインスタンスを作成しているわけではありません。 ElemAlg そのため、初期化されていないポインタに対してメンバ関数を呼び出していることになります。

呼び出しているメンバ関数は仮想関数ではないので、コンパイラは実行時の検索を行う必要がありません。 GetQuiz . しかし this のポインタはゴミになります。 ea は初期化されていないので、メンバー変数にアクセスした瞬間 ( difficultyLevel というように、未定義の動作が発生します。あなたの場合、未定義の動作はアクセス違反につながります。

を初期化するか ea :

ElemAlg *ea=new ElemAlg;
ea->GetQuiz(1)

または、ヒープに割り当てる必要がない場合は、そうしてください。

ElemAlg ea;
ea.GetQuiz(1)