【问题标题】:C++ Vector Not Initialized Empty When In Release Mode在发布模式下,C++ 向量未初始化为空
【发布时间】:2018-03-04 05:25:12
【问题描述】:

这是我在堆栈溢出中发布的比较模糊的错误之一,因此如果信息似乎有点缺乏,我提前表示歉意。我有一个相当大的项目,它使用静态向量来包含应用程序生命周期的信息。在调试模式下,一切都顺利进行,但在发布模式下,向量似乎未初始化。当我逐步完成解决方案时,我可以看到在发布模式下,向量的大小是随机的,并且充满了每次运行应用程序时都会发生变化的废话,这让我相信它们没有初始化,只是从堆中读取随机信息。对于大规模的项目,显示所有代码并请求帮助解析整个内容对我来说既困难又不公平,因此我提取了相关信息。这样做的问题是提取的代码中不会出现相同的错误,好像构建经历了不同的优化,因此不会产生相同的错误。

长话短说,我想知道它们是否是一种我可以强制初始化大小为 0 的向量的方法,这样这样的初始化就不会得到优化。

如果有帮助,这里是提取代码:

#include <vector>
#include <iostream>
using std::getchar;
using std::vector;
class Entity {
public:
    short id;
    Entity(short i) : id(i) {

    }
};

class EntityManager {
    static Entity& CreateEntity(vector<Entity> &entities, unsigned short i);
public:
    static vector<Entity> dynamicEntities;
    static vector<Entity> staticEntities;

    static Entity& CreateDynamicEntity();
    static Entity& CreateStaticEntity();
};

vector<Entity> EntityManager::dynamicEntities;
vector<Entity> EntityManager::staticEntities;

Entity& EntityManager::CreateEntity(std::vector<Entity> &entities, unsigned short i) {
    entities.push_back(Entity((entities.size())));
    Entity& entity = entities.back();
    return entity;
}

Entity& EntityManager::CreateDynamicEntity() {
    return CreateEntity(dynamicEntities, 1);
}

Entity& EntityManager::CreateStaticEntity() {
    return CreateEntity(staticEntities, 0);
}

int main() {
    Entity& e = EntityManager::CreateDynamicEntity();
    std::cout << e.id;
    getchar();
    return 0;
}

提前感谢您的帮助。

【问题讨论】:

  • 未指定不同翻译单元中定义的全局变量的初始化顺序。我的猜测是,你有一个全局对象A,它的构造函数依赖于另一个在不同源文件中定义的全局对象B 的状态。恰好A首先被初始化,当它的构造函数尝试访问B时,程序表现出未定义的行为。
  • @IgorTandetnik 好吧,这对我来说很有意义,我能做些什么吗? EntityManager 类几乎完全是静态的,所以我不确定调用它的构造函数是否会有很大帮助
  • 您可以使用单例模式,在第一次使用时按需创建单例。像这样:class Singleton { static Singleton&amp; GetInstance() { static Singleton instance; return instance; }; 使这些向量成为普通(非静态)数据成员。您可以保留静态成员函数,这将简单地转发到GetInstance() 上的非静态成员函数。
  • @IgorTandetnik 好的,为了确保我理解正确,我将为每个静态向量创建一个单例,并通过它们各自的单例包装器访问这些向量?
  • 你可以。就个人而言,我会将整个 EntityManager 变成一个单例,并使向量成为非静态成员。

标签: c++ vector initialization c++14 release


【解决方案1】:

您的问题似乎是由于全局变量的初始化顺序不确定。

使它们具有确定性的一种方法是用函数包装数据。

而不是使用

vector<Entity> EntityManager::dynamicEntities;

使用

vector<Entity>& EntityManager::getDynamicEntities()
{
   // This guarantees that entities is initialized properly 
   // before it is accessed by calling code.
   static vector<Entity> entities;
   return entities;
}

当然,这意味着将 EntityManager 更改为:

class EntityManager {
    static Entity& CreateEntity(vector<Entity> &entities, unsigned short i);
  public:
    static vector<Entity>& getDynamicEntities();
    static vector<Entity>& getStaticEntities();

    static Entity& CreateDynamicEntity();
    static Entity& CreateStaticEntity();
};

【讨论】:

  • 我有点困惑,getDynamicEntites() 完成后,static vector&lt;Entity&gt; entities; 不会超出范围吗?每次我尝试访问动态实体时,这不会初始化一个全新的向量吗?
  • @Ryoku,不,他们不会。 static 变量保证存在于对函数的所有调用中。只要程序存在,它们就会存在。
  • 哇,太酷了不知道。所以这意味着它也不应该产生任何额外的开销“确保”它首先正确初始化。也就是说,它不应该在程序的生命周期内多次执行static vector&lt;Entity&gt; entities 行(而不是每次我尝试访问其中一个向量时都执行而不做任何事情),对吗?
  • @Ryoku,确实是这样。
  • 这就像一个魅力,非常感谢你!对于全局变量初始化的非确定性,我仍然(显然)是新手(因为直到几分钟前我才知道这是一件事)。我得调查一下那个。无法保证在需要之前初始化某些东西似乎有点可怕。此外,我认为这将是一个更难的问题,因为我无法合理地复制该问题,我只是惊讶于 stackoverflow 上有多少乐于助人和明智的人,再次感谢您
猜你喜欢
  • 2012-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-10
  • 1970-01-01
  • 2015-09-20
  • 2012-06-21
相关资源
最近更新 更多