【问题标题】:Do I have to allocate everything on the heap (that gets stored within) heap containers?我是否必须在堆(存储在)堆容器中分配所有内容?
【发布时间】:2011-01-10 05:10:21
【问题描述】:

在使用 new 关键字时,我将覆盖 new 运算符以手动分配堆空间。

通常使用堆栈分配的堆容器,并带有指向其项目的指针-

CArray<CObject*> objects;

-很好。但我很挑剔,我想做缓冲区-

CArray<CObject> objects;

-让我修改 POD 类型。因此,我将它们分配在自然适合它们使用的堆栈上:

CVertex vertex;
objects.push_back(vertex);

但是它破坏了堆(我经历了一个糟糕的星期)并给出了一个疯狂的错误:

0xC0000017: Not Enough Quota.

我预先分配数组对象,然后在 push_back() 内部使用 = 运算符。

我通过在堆上分配临时对象然后将它们添加到数组中解决了这个问题。但这似乎不对,我就是不明白。

根据要求,一些代码:

CArray::push_back( T& newElement )
{
m_internalElements[allocatedSize] = newElement;
allocatedSize++;
}

CArray::preallocate_and_initialize( size_t itemCount )
{
T* newInternalElements = mem::allocate_and_initialize( T, itemCount );
//copy over
}

请注意,这一切都适用于堆分配的 CVertex,因为我在缓冲区元素的二进制搜索中使用这些对象(在索引缓冲区中为给定顶点找到正确的项目)和它可以完美地构建网格!

【问题讨论】:

  • 如何在 operator= 中分配堆栈上的对象并期望它们在函数中存在?如果它们是,一旦你离开那个范围,它们就会死掉并给你留下一个悬而未决的参考。还是我误会了什么?
  • 嗨 zneak,它们是通过调用构造函数预先分配的,然后 = 运算符在超出范围之前从堆栈实例复制字段。
  • 您能否将代码发布到您的operator newCArray::push_back 版本中
  • 您是否在push_back() 的任何地方进行边界检查?还有一点,如果它适用于指针,但不适用于堆栈分配的对象,CVertex::operator= 可能是问题所在。
  • 完成 :) 复制 ctor 由 msvc++ 自动生成,它是 POD 类型:vec4 Pos; vec4 正常;我只是仔细检查了 CVertex 的大小,它是 sizeof(vec4)*2。

标签: c++ heap-memory allocation


【解决方案1】:

CVertex 是从 CObject 派生的?如果 CVertex 有更多实例数据,则不能这样做。 (我的意思是你不能创建一个 CObjects 数组并将 CVertexes 放入其中) 编译器应该在 CObject 数组中创建多大的插槽,它们将是 CObject 大小的,然后您将尝试在插槽中放置更大的东西 -> bang

您应该将 boost::shared_ptr 对象放入您的数组中。一旦你有了这个成语,你就再也不会回去了

【讨论】:

  • 是的,在这种情况下,我明确地使用了一个包含 CVertex 元素的 CArray。我不使用指针,因为我需要将连续缓冲区中的数据复制到 DirectX 缓冲区:)
【解决方案2】:

0xC0000017STATUS_NO_MEMORY。即,您用尽了虚拟地址空间,即您使用了太多内存。

如果您希望有很多元素,在重复调用push_back 之前预留空间应该足以避免内存不足。您可以使用CArray::SetSize(0, itemCount) 为您的所有元素保留空间。

【讨论】:

  • 不,这就是为什么这是一个如此疯狂的错误!我可以在这发生之前分配 2GB :)
  • 这是您在 Win32 上可以分配的连续虚拟内存的限制。
猜你喜欢
  • 2017-11-03
  • 2021-12-09
  • 2016-05-19
  • 1970-01-01
  • 2019-12-10
  • 2020-09-01
  • 1970-01-01
  • 2020-09-02
  • 1970-01-01
相关资源
最近更新 更多