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<Case>), 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<T>::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++ 向量上的分配错误的主要内容,如果未能解决你的问题,请参考以下文章