I’ve been trying to debug this for hours now with no luck. I know you guys will solve the problem within minutes, so here’s the situation:
I’ve got ~400 .cpp/.h files called ProblemX.cpp/ProblemX.h (where X is a number from 1 to 400). Each file contains the solution for a math related problem. I would like to have the problems register themselves at compile time to a global map with a unique key (just an int will work) and have the value be a pointer to the function that kicks off the math problem solution.
The global map is created and handled in files called Problem.h/Problem.cpp. However, I’m getting an “Access violation reading location 0x00000004” when the first Problem attempts to self-register in the map. The code is as follows:
In the ProblemX.h files (problem1 kicks off the solution for this problem):
#ifndef PROBLEM1_H
#define PROBLEM1_H
#include "Problems.h"
#include <string>
std::string problem1();
static int rc1 = registerProblem(1, problem1);
#endif
In the Problems.h file (problemFinder is the function that uses the global map to call the appropriate function pointer):
#ifndef PROBLEMS_H
#define PROBLEMS_H
#include <string>
int registerProblem(int problemNum, std::string (*problemFunc)(void));
std::string problemFinder(int problemNum);
#endif
In Problems.cpp:
#include "Problems.h"
#include <iostream>
#include <map>
using namespace std;
map<int,std::string (*)(void)> problems_map;
int registerProblem(int problemNum, string (*problemFunc)(void)) {
int rc = 0;
problems_map[problemNum] = problemFunc;
return rc;
}
string problemFinder(int problemNum) {
string retStr = "";
retStr = problems_map[problemNum]();
return retStr;
}
The access violation occurs where “problems_map[problemNum] = problemFunc;”.
Thanks!
As the enigmatically named user93353 answered, the
problems_mapglobal is not guaranteed to be constructed before globals in other files.To avoid the static initialization order fiasco, make
problems_mapa local static, that will be init’d on its first use:Then use it like so:
This ensures the map gets created as soon as it’s needed, not just when the global constructors from
Problems.cppget run, which might be (and in your case definitely is) after the globalrc1variable gets initialised.