【问题标题】:Access violation inserting element into global map [duplicate]访问冲突将元素插入全局地图[重复]
【发布时间】:2014-09-15 21:40:03
【问题描述】:

我正在返回一个在大约 4 年后可以正常工作的 C++ 应用程序。我的第一个任务是将其从 Windows XP/.NET Framework 3.5/Win32/VS2008 更新到 Windows 7/.NET Framework 4.5/Win64/VS2012。

程序有一个全局映射声明,现在它在第一次尝试插入元素时收到访问冲突,而之前它运行正常。我在这里查看了所有相关参考资料,但找不到解决方案,因此我将不胜感激。代码如下所示:

Attributes.h

static void LoadAttributes(void);

Attributes.cpp

#include "sys\types.h"
#include <map>

static map<string,int> AttributeTable;

void LoadAttributes(void)
{
   AttributeTable.insert(pair<string,int>("attribute1",1));
   AttributeTable.insert(pair<string,int>("attribute2",2));
   ...
}

一旦它执行第一次插入,它就会产生访问冲突。这看起来像是一个初始化问题,因为智能感知显示了地图的地址,但未定义 _Right_Left 指针:(_Right=?????, _Left=?????)

在方法中本地声明的映射具有这些值。我读过,如果静态映射和初始化它的静态方法在不同的文件中,那么初始化的顺序不能保证,但它们都在同一个文件中。

编辑——为了回应 jww,Dennis Chong 等人。正如我上面提到的,这个问题被标记为重复的问题涉及映射和初始化它的方法在 2 个不同的 cpp 文件中定义的情况。我了解在这种情况下无法保证订单。然而,解决方案指出,当两者在同一个 cpp 文件中时,初始化的顺序很好理解,并且应该是声明项目的顺序。由于这个原因,在我看来问题是不同的。

【问题讨论】:

  • 听起来像 static initialization order fiasco。只是避免类类型全局变量。考虑使用 Meyers 单例而不是直接变量。
  • 如果LoadAttributes() 被其他全局构造函数调用,那么初始化顺序将是不确定的。您可以先将地图设为静态变量 inside LoadAttributes,然后看看会发生什么。
  • 无关:我是唯一一个觉得奇怪的人static void LoadAttributes(void);header 文件中吗?声明为static,LoadAttributes 对当前翻译单元是本地的,因此除非 Attributes.cpp 被 #include-ed 到其他一些 .cpp 文件中(这将是可怕的),标题中的声明似乎毫无意义且没有根据(而且一点儿也不臭)。
  • @WhozCraig:我只是没看到。经常发生。我(或一个人)没有看到完全出乎意料的情况。有一个关于这个的旧 SciAm 视频,一个穿着大猩猩服装的男人在一些专注于球赛的人中间跳华尔兹舞。他们没有注意到他。
  • 对不起,我记错了,是那些专注于计算球传球的观众没有注意到(意外的)大猩猩。视频:youtube.com/watch?v=vJG698U2Mvo

标签: c++ windows visual-studio-2012 win64


【解决方案1】:

改变这个:

static map<string,int> AttributeTable;

void LoadAttributes(void)
{
   AttributeTable.insert(pair<string,int>("attribute1",1));
   AttributeTable.insert(pair<string,int>("attribute2",2));
   ...
}

收件人:

map<string,int>& GetAttributeTable()
{
    static map<string,int> AttributeTable;
    return AttributeTable;
}

void LoadAttributes(void)
{
    map<string,int>& AttributeTable = GetAttributeTable();
    AttributeTable.insert(pair<string,int>("attribute1",1));
    AttributeTable.insert(pair<string,int>("attribute2",2));
    ...
}

【讨论】:

  • 这个答案假设了一个可能的具体原因,但绝不是肯定的。然而,这是一个很好的第一步。如果它解决了问题,那很好;如果不是,则排除了一种可能性。
  • @Cheers - _Right=?????, _Left=????? 放弃它。但你是对的 - Visual Studio 非常随和,通常不会遇到这个问题。 Apple 是最不适应的,静态全局变量(甚至访问器)肯定会出现问题。对于 Apple,请参阅 Specify construction/destruction order of static locals in different accessors
  • 这解决了 void LoadAttributes(void) 问题。但是,现在,在我引用地图的任何地方,我都必须再次调用 GetAttributeTable(),它会返回一个空地图,例如,即使 LoadAttributes 终止时有 339 个条目,以下内容也会返回 0 索引:
  • map::iterator indx; mapAttributetable=GetAttributeTable(); indx=AttributeTable.find("attribute1");
  • 该问题由 jww 提出的解决方案的变体解决,该变体也类似于参考解决方案中的解决方案。无论 map 和 initialize 例程是在同一个文件中还是在不同的文件中,似乎都存在初始化问题。感谢大家的回复。
猜你喜欢
  • 1970-01-01
  • 2013-02-25
  • 1970-01-01
  • 2019-10-24
  • 1970-01-01
  • 2021-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多