使用 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