[英]Access violation when inserting element into global map
我一直試圖調試這幾個小時,沒有運氣。 我知道你們會在幾分鍾內解決問題,所以情況如下:
我有~400個.cpp / .h文件,名為ProblemX.cpp / ProblemX.h(其中X是1到400之間的數字)。 每個文件都包含與數學相關的問題的解決方案。 我想讓問題在編譯時自己注冊到具有唯一鍵的全局映射(只有一個int可以工作),並且值是指向啟動數學問題解決方案的函數的指針。
全局映射在名為Problem.h / Problem.cpp的文件中創建和處理。 但是,當第一個問題試圖在地圖中自行注冊時,我收到“訪問沖突讀取位置0x00000004”。 代碼如下:
在ProblemX.h文件中(problem1啟動了解決此問題的方法):
#ifndef PROBLEM1_H
#define PROBLEM1_H
#include "Problems.h"
#include <string>
std::string problem1();
static int rc1 = registerProblem(1, problem1);
#endif
在Problems.h文件中(problemFinder是使用全局映射調用相應函數指針的函數):
#ifndef PROBLEMS_H
#define PROBLEMS_H
#include <string>
int registerProblem(int problemNum, std::string (*problemFunc)(void));
std::string problemFinder(int problemNum);
#endif
在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_map [problemNum] = problemFunc;”的位置。
謝謝!
正如神奇命名的user93353所回答的那樣,不能保證在其他文件中的全局變量之前構造problems_map
全局。
為了避免靜態初始化順序失敗,make 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;
這確保了地圖在需要時立即創建,而不僅僅是在來自Problems.cpp
的全局構造函數運行時,在全局rc1
變量初始化之后可能(並且在您的情況下肯定是)。
小心使用這樣的靜態。 它們的定義順序可以產生影響。 變量可能存在,但不一定構造。 這實際上是我昨天的屁股,所以它在我的記憶中是新鮮的。
在Problems.cpp
,訂單的定義是:
static int rc1 = registerProblem(1, problem1);
map<int,std::string (*)(void)> problems_map;
這意味着rc1
在problems_map
之前被初始化。
因此,您的問題就出現了,因為調用registerProblem
來初始化rc1
並且它使用尚未構造的problems_map
。
我一直以為編譯器會解決這個問題。 但是當你考慮它時,一般情況下很難考慮(特別是如果你最終會有相互依賴)。 所以我想唯一明智的做法是期望程序員以正確的順序放置他們的靜態定義,就像他們應該對任何其他代碼語句一樣。
查看構造函數的C ++ FAQ。 特別是檢查問題10.14到10.18 - “靜態初始化命令慘敗”。
什么是“靜態初始化命令慘敗”?
破壞程序的一種微妙方式。
靜態初始化順序fiasco是C ++中一個非常微妙且常被誤解的方面。 不幸的是,它很難被發現 - 錯誤經常發生在main()開始之前。
簡而言之,假設您有兩個靜態對象x和y,它們存在於單獨的源文件中,比如x.cpp和y.cpp。 進一步假設y對象的初始化(通常是y對象的構造函數)調用x對象上的某個方法。
而已。 就這么簡單。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.