C++: Access violation writing location

user3001499 picture user3001499 · Oct 20, 2014 · Viewed 42.5k times · Source

Using: MSVS2012

Code

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 is definitely passed an integer between 1 and 4, this is verified before the method is called

difficultyLevel is a string defined in the header file.

The compiler throws an Unhandled exception and Access violation writing location ... as soon as it hits the first if function.

If I remove the if functions and define difficultyLevel as algE just for testing the same problem.

If I remove difficultyLevel entirely and just open the file as "algE.txt" and "algEAnswers" then I get the same problem but at a different memory location once the code hits the while loop.

Answer

Sean picture Sean · Oct 20, 2014

Your problem is here:

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

You're not creating an instance of ElemAlg, so you're calling a member function on an uninitialized pointer.

Because the member function you are calling isn't virtual the compiler won't have to do any runtime lookup, which is why the call goes to GetQuiz. However, the this pointer will be garbage (as ea is uninitialized), so the moment you access a member variable (such as difficultyLevel) you'll have undefined behaviour. In your case the undefined behaviour leads to an access violation.

Either initialize ea:

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

or, if you don't need to allocate it on the heap just do:

ElemAlg ea;
ea.GetQuiz(1)