C++ 向量上的分配错误

Posted

技术标签:

【中文标题】C++ 向量上的分配错误【英文标题】:allocation error on C++ vector 【发布时间】:2017-07-18 08:21:02 【问题描述】:

我正在尝试分配一个vector<vector<Class>>,其中包含一个vector<AnotherClass>,但我得到一个分配错误,所以我的问题是:变量上给出的max_size() 适用于我程序的所有向量?

我可以通过改变我的编译器来改变这个限制吗?

这是我用来检查的代码:

class Couches

public:
    Couches() : m_value(-1) 
    ~Couches() 

    void initialize(const int& value) 
        m_value = value;
    
private :
    int m_value;
;

class Case

public :
    Case() 
    ~Case() 

    void initialize(const int& hauteur) 
        m_couches.resize(hauteur);
        for (int i(0); i<hauteur;i++)
            m_couches[i].initialize(i);
    
private :
    vector<Couches> m_couches;
;


void bug1()

    vector<vector<Case>> m_cases;
    m_cases.resize(5000, vector<Case>(5000));

    cout<< m_cases.max_size()<<" " <<5000*5000*20<<endl;

    for (int i(0); i<m_cases.size(); i++)
    
        for (int j(0); j<m_cases[i].size(); j++)
        
            m_cases[i][j].initialize(20);
        
    

我的 max_size 为 357M

编辑:对不起,我说的是错误,但这是调试器给出的错误:

#1 0x405b36 operator new(unsigned int) () (??:??)

#2 0x490f58 typeinfo for std::time_put<wchar_t, std::ostreambuf_iterator<wchar_t, std::char_traits<wchar_t> > > () (??:??)

#3 0x4761ac std::allocator_traits<std::allocator<Couches> >::allocate(__a=..., __n=0) (D:/CodeBlocks/MinGW/lib/gcc/mingw32/4.9.2/include/c++/bits/alloc_traits.h:357)

terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc

我使用了一个初始化函数,因为它是一个 mcve,在我的原始代码中我需要这个函数。

【问题讨论】:

max_size() 由库实现者实现,是否可以更改取决于实现者。 1) 但我得到一个分配错误 这是..?请复制粘贴该错误消息。 2) 为什么你的类使用initialize 方法,而构造函数为空?由于类的初始化,是构造函数的工作。 不过,您所写的并不是完整的错误消息。 复制粘贴完整的错误信息,逐字逐句。 此值通常反映容器大小的理论限制。在运行时,容器的大小可能会被限制为小于 max_size() 可用 RAM 量的值 en.cppreference.com/w/cpp/container/vector/max_size 发布堆栈跟踪的根节点几乎是无用的:/ 如果您不确定读者需要看到什么,请不要发布您认为他们的内容需要看;发布整个事情。 【参考方案1】:

vector::max_size() 与在没有任何其他内存使用的情况下 单个 向量可以得到多大有关。您的向量都没有接近那个大小。最大的是 5000,个人分配 5000 * max(sizeof(vector&lt;Case&gt;), sizeof(Case)) 对我来说是 80,000。

您看到的错误是所有 25,000,000 Cases 和 500,000,000 Couches 的总分配超出了您程序中的地址空间

【讨论】:

好吧,这很清楚,我用 64 位编译,当然这很好!那我能阻止我的内存溢出的开始吗? @PierreChéneau:仅分配您实际使用的内存。是否需要使用 5000*5000 Cases?你需要在每个沙发上使用 20 张沙发吗? m_value 需要int 吗?也许你可以为它使用更小的数据类型,比如 short/char。 这是一个找到我的程序限制的例子,所以是的,我将有更少的案例和沙发。我没有考虑使用short,我会使用它。它更多的是一种检测计算机速度变慢并阻止程序的方法。【参考方案2】:

max_size() 是可以放置在向量中的最大项目数,此数字受系统位限制。如果您使用的是 2^32 char 值的 32 位系统。您正在达到系统或库实现限制,这就是您收到 375M

的原因

您应该使用std::vector&lt;T&gt;::size_type 作为您的数组索引

【讨论】:

对我的数组索引使用 std::vector ::size_type 会有什么变化。可以举个例子吗? 这里有一个很好的解释paercebal's answer @PierreChéneau 容器的size_type 是您应该使用它来引用其大小或其中的索引 - 句点。 int 几乎肯定不能代表容器可能具有的最大大小或索引:int 的最大值将低于 std::size_t,因为 (A) 它可能具有较低的位宽度和 ( B)即使具有相同的位宽度,它也是有符号的,因此最大值相应地减少了一半。 所以在我的 boucle 中,如果我写: for (auto i (0) ; i 【参考方案3】:

我想你是用 32 位编译代码的。

这里有一个猜测,为什么将 341M 设为 max_size。一个典型的实现将为您提供 SIZE_MAX/sizeof(element_size) 的值。 SIZE_MAX 为 4GB-1。然后检查包含另一个向量的向量的max_size() 值。一个典型的 sizeof(vector) 是 12。所以,给定的答案是 4GB/12=341M。注意:实现可以提供它想要的任何max_size 值。

以 64 位编译您的代码,如果您有必要的内存,您的代码将运行。

注意:在您的代码中,您不必担心max_size(),因为您的向量不包含那么多元素。我的意思是,没有一个向量实例具有那么多元素。问题是您的总内存消耗很大,不适合 ~2GB,这是 32 位中典型的最大允许进程大小。所以我认为你的程序内存不足,向量大小没有问题。

注2:我使用了M=2^20,G=2^30

【讨论】:

为什么您认为增长率会影响可存储的最大大小?它没有。它只影响重新分配发生时可用容量 的增长方式。我不知道为什么这被标记为已接受。我错过了什么? 如果它依赖于一个充满“我认为”或“这 [...] 只是一个猜测”的想法,我会说不要发布作为答案的东西。 @underscore_d 这与向量的实现直接相关。当向量容量增加时,需要复制元素并因此使用额外的空间 @Swift:是的,是的。 :) 这就是我说“典型”的原因。数量级。所以OP可以理解发生了什么。我们可以讨论单个分配的开销、内存/地址空间碎片等。我认为这不是重点。 @underscore_d:实际上,这就是我提到增长率的确切原因。但是,我想了想,这不是 1.5 的答案,所以我开始检查实现。这是因为,如果当前大小为 X,则在增长期间,需要 X + rate*X 内存。如果 max 是 2GB,那么除以 1.5 是没有意义的,因为我们需要除以 (1+rate),它至少是 2。如果 max 是 4GB,这意味着除以 ~2.93 (1GB/0.341GB),其中rate 是 1.93,这是一个奇怪的数字。

以上是关于C++ 向量上的分配错误的主要内容,如果未能解决你的问题,请参考以下文章

c++向量分配错误分段错误

C++ 向量分配器错误

为啥 C++ 标准向量在分配或调整大小时会出现段错误? [关闭]

C++ 为啥在向量段错误中放置对象?

c++中向量的限制

C ++中动态分配的向量中的分段错误