C++ 将元素插入全局映射时发生访问冲突
我已经试着调试了好几个小时了,但运气不好。我知道你们会在几分钟内解决问题,所以情况如下: 我有~400.cpp/.h文件,名为ProblemX.cpp/ProblemX.h(其中X是1到400之间的数字)。每个文件都包含一个数学相关问题的解决方案。我想让问题在编译时用一个唯一的键(只需要一个int)将自己注册到一个全局映射,并让值成为启动数学问题解决方案的函数的指针 全局映射在名为Problem.h/Problem.cpp的文件中创建和处理。然而,当第一个问题试图在映射中自注册时,我得到了一个“访问冲突读取位置0x00000004”。代码如下: 在ProblemX.h文件中(problem1启动此问题的解决方案):C++ 将元素插入全局映射时发生访问冲突,c++,map,C++,Map,我已经试着调试了好几个小时了,但运气不好。我知道你们会在几分钟内解决问题,所以情况如下: 我有~400.cpp/.h文件,名为ProblemX.cpp/ProblemX.h(其中X是1到400之间的数字)。每个文件都包含一个数学相关问题的解决方案。我想让问题在编译时用一个唯一的键(只需要一个int)将自己注册到一个全局映射,并让值成为启动数学问题解决方案的函数的指针 全局映射在名为Problem.h/Problem.cpp的文件中创建和处理。然而,当第一个问题试图在映射中自注册时,我得到了一个“
\ifndef问题1\u H
#定义问题1\u H
#包括“Problems.h”
#包括
std::string problem1();
静态int rc1=寄存器问题(1,问题1);
#恩迪夫
在Problems.h文件中(problemFinder是使用全局映射调用相应函数指针的函数):
\ifndef问题\u H
#定义问题
#包括
int registerProblem(int problemNum,std::string(*problemFunc)(void));
字符串problemFinder(int problemNum);
#恩迪夫
在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;
}
#包括“Problems.h”
#包括
#包括
使用名称空间std;
地图问题;
int registerProblem(int problemNum,string(*problemFunc)(void)){
int rc=0;
problems\u map[problemNum]=problemFunc;
返回rc;
}
字符串problemFinder(int problemNum){
字符串retStr=“”;
retStr=问题映射[problemNum]();
返回retStr;
}
访问冲突发生在“problems\u map[problemNum]=problemFunc;”的位置
谢谢 小心使用这样的静态。它们的定义顺序可能会有所不同。变量可能存在,但不一定是构造的。这实际上是昨天咬了我一口,所以我记忆犹新 在
Problems.cpp
中,事物的定义顺序为:
static int rc1 = registerProblem(1, problem1);
map<int,std::string (*)(void)> problems_map;
static int rc1=寄存器问题(1,问题1);
地图问题;
这意味着rc1
在problems\u map
之前被初始化
因此,您的问题是因为调用了registerProblem
来初始化rc1
,并且它使用了尚未构造的问题映射
我一直以为编译器会解决这个问题。但是当你考虑它的时候,一般的情况太难考虑了(特别是如果你最终的相互依赖)。所以我想唯一需要做的事情就是程序员要把他们的静态定义放在正确的顺序,就像他们应该和任何其他代码语句一样。 < P>检查C++常见问题。特别检查问题10.14至10.18-“静态初始化订单失败”
什么是“静态初始化顺序失败”
一种使程序崩溃的微妙方式
静态初始化顺序的失败是一个非常微妙和常见的错误
误解C++的方面。不幸的是,这很难被发现-
这些错误通常发生在main()开始之前
简而言之,假设有两个静态对象x和y存在于
单独的源文件,例如x.cpp和y.cpp。进一步假设
y对象的初始化(通常是y对象的构造函数)
调用x对象上的某个方法
就这样。就这么简单
正如神秘命名的user93353所回答的那样,problems\u map
global不能保证在其他文件中的globals之前构造
为避免静态初始化顺序失败,请将问题\u map
设置为本地静态,该静态将在首次使用时初始化:
map<int,std::string (*)(void)>&
get_problems_map()
{
static map<int,std::string (*)(void)> problems_map;
return problems_map;
}
这可以确保在需要时立即创建映射,而不仅仅是当Problems.cpp
中的全局构造函数运行时,这可能是(在您的情况下肯定是)在全局rc1
变量初始化之后。400数学相关问题?我闻到欧拉计划的味道了吗?哈哈,我的朋友。几个星期前开始学习,试图重新学习C++。令人上瘾的家伙…嘿,伙计,我感谢你的回答,但我不确定我是否完全理解。“static int rc1”的定义在Problem1.h中,而不是Problems.cpp中。您是否暗示Problems.cpp文件将始终在Problem1.h文件之后执行?有没有办法解决这个问题?这个答案不太准确,rc1
没有在Problems.cpp中初始化,这就是问题所在。单个文件中的初始化顺序定义良好,但不能保证全局文件在单独的.cpp
文件中的初始化顺序,rc1
和问题\u map
在单独的文件中,Problem1.cpp
和问题.cpp
噢,不知何故,我最终认为问题1.h
就是问题.h
。这本质上是相同的问题(初始化顺序),但不是因为我描述的确切原因。具体来说,给出了一个极好的答案。解决了这个问题,并解释了它的工作原理。谢谢哎呀,刚才注意到我在get\u problems\u map()
函数中粘贴了static
关键字,这对它的工作至关重要!现在更正。
static int rc1 = registerProblem(1, problem1);
map<int,std::string (*)(void)> problems_map;
map<int,std::string (*)(void)>&
get_problems_map()
{
static map<int,std::string (*)(void)> problems_map;
return problems_map;
}
get_problems_map()[problemNum] = problemFunc;