使用 new[] 安全地分配动态数组

Posted

技术标签:

【中文标题】使用 new[] 安全地分配动态数组【英文标题】:Safely allocating dynamic arrays with new[] 【发布时间】:2015-06-16 18:38:32 【问题描述】:

这个想法是加载 Wavefront OBJ 文件并使用 DirectX 11.0 渲染它。到目前为止一切正常,除了几何体的实际加载。

我分配一个指针数组来包含我的顶点位置、纹理坐标和法线:

pfVertices_ = new float[nTotalVertices_ * 3];
pfNormals_ = new float[nTotalVertices_ * 3];
pfTexcoords_ = new float[nTotalVertices_ * 2];

当然,我会释放它们:

delete[] pfVertices_;
delete[] pfNormals_;
delete[] pfTexcoords_;

当我尝试加载包含大约 9200 个顶点的模型时,我遇到了访问冲突。我明白问题是什么,我只是不知道如何解决它。我试过malloc()free(),但是AFAIK 你不能把void* 转换成float* 而不自找麻烦,它仍然给我访问冲突。

所以,我的问题: 有没有一种安全的方法来动态分配大数组,还是我应该忍受new 的缺点?

编辑:所以是的,我知道std::vector 从一开始就存在。由于一些糟糕的体验,我回避了它,并且因为当图形引擎在 GPU 上变得繁重时,我担心它的性能。

无论如何,我将所有内容都转换为std::vector,并且我没有再次遇到访问冲突。但是我的几何图形是不可见的。我(有点)尝试过相机方向/位置是否有问题,但事实并非如此。我还检查了图形调试器,没有任何明显的问题。我以前遇到过这个不可见的几何问题,但后来它与光栅化状态有关,这里不可能。有人对在哪里寻找问题有什么建议吗?

【问题讨论】:

您正在正确分配和删除内存,您的问题在其他地方。如果分配是您得到std::bad_alloc 的问题,则访问冲突是另一个问题。 这里没有明显的问题。这应该有效。恐怕你的问题可能出在其他地方。你听起来像是在 Windows 上;你可以使用像 Linux 的 valgrind 这样的内存边界检查工具吗? 访问冲突不是 'new' 抛出的 'std::bad_alloc' 异常,因此您没有分配问题。 顺便提一下,因为你很着急,一些快速而肮脏的调试技巧:用new float[size*2] + (size/2)分配,然后用delete[] (ptr - size/2)释放。这将为您提供数组前后缓冲区的size/2 索引。如果您的程序停止崩溃,则说明存在缓冲区溢出问题。 另外,请尝试完全注释掉您的 delete[] 行。你的程序会像没有明天一样泄漏内存,但如果它停止崩溃,你就有一个 using-pointer-after-freeing 问题。 【参考方案1】:

是的!你绝对应该使用std::vector 而不是new[]!它将为您完成所有内存管理,您可以使用std::vector::at 或platforms debugging facilities 进行范围检查访问。

这本身当然不能防止访问冲突,但它能够非常详细地告诉您(或者至少比您使用new[] 所拥有的更精确)它们发生在哪里,例如您尝试访问的索引以及数组的实际大小。

有了这些信息,找到根本问题通常比仅仅从一个毫无用处的“分段错误”中容易得多。

使用std::vector 还会让您更难犯一些(遗憾的是仍然很常见)错误,例如“免费使用”错误。

【讨论】:

不管怎样,他们的分配不是问题的原因,所以切换到std::vector 不会解决他们的问题。 @CoryKramer 但它会让他们更好地了解问题所在,因为您可以用良好的调试行为来换取愚蠢的 UB 崩溃。 不!只需编写正确的代码(我从不使用 std::vector::at) @DieterLücking 我也没有,但我确实使用我的平台提供的调试工具来告诉我(至少在某些情况下)我什么时候搞砸了。 “只要写正确的代码”就和医生说的“别生病”一样有用。 std::vector::at 没有调试工具。

以上是关于使用 new[] 安全地分配动态数组的主要内容,如果未能解决你的问题,请参考以下文章

数组和链表

分配一维动态数组or 二维动态数组的方法以及学习 new 方法or vector

怎么使用new操作符创建动态数组?

动态分配数组时的C ++ new vs new [] [重复]

c++ 动态分配二维数组 new 二维数组

C++ 对象的动态建立 & 释放