gpt4 book ai didi

c++ - 大型 C++ 数组导致 iOS 上出现段错误

转载 作者:可可西里 更新时间:2023-11-01 05:42:45 26 4
gpt4 key购买 nike

我正在使用 C++ 构建一个 iOS 应用程序,遇到了一个大数组问题。问题是,如果数组达到一定大小,我将得到一个类型为 EXC_BAD_ACCESS (SIGSEGV) 的异常,子类型为 KERN_PROTECTION_FAILURE,带有段错误 (11) 终止信号。

有趣的是,无论我将数组放在堆栈上还是堆上,我都会收到该异常。

将数组放入堆栈的代码如下所示:

class Model
{
public:
Model() { };

private:
static constexpr std::size_t VERTEX_COUNT = 25894;

Vertex _vertices[VERTEX_COUNT] =
{
{ { 46.629387f, 647.478271f, 58.987785f }, { 0.140482f, 0.716024f, 0.683795f }, false },
{ { 86.409439f, 639.203247f, 57.095085f }, { 0.273239f, 0.689217f, 0.671059f }, false },
{ { 94.825722f, 586.618164f, 91.772812f }, { 0.375726f, 0.404750f, 0.833671f }, false },
{ { 50.570183f, 586.068481f, 100.536209f }, { -0.003906f, 0.451161f, 0.892434f }, false },
// 25894 array entries in total
};

// all the rest
}

用于填充数组的结构如下所示:

struct Vertex
{
Vertex()
{
}

Vertex(glm::vec3 coords, glm::vec3 norm, bool selected) :
coordinates(coords),
normal(norm),
isSelected(selected)
{
}

glm::vec3 coordinates;
glm::vec3 normal;
bool isSelected;
};

一旦模型实例被实例化,上述代码就会在 iOS 11.4 上崩溃。

现在,即使我换行也会发生这种情况

Vertex _vertices[VERTEX_COUNT] =

到(在堆上分配内存)

Vertex* _vertices = new Vertex[VERTEX_COUNT]

或到

std::unique_ptr<Vertex[]> _vertices = std::unique_ptr<Vertex[]>(new Vertex[VERTEX_COUNT]

或者将整个数组定义移动到 Model 的构造函数中。

到目前为止,我唯一能让它工作的方法就是改变

Vertex _vertices[VERTEX_COUNT] =

static constexpr Vertex _vertices[VERTEX_COUNT] =

并将相应的 constexpr 构造函数添加到 Vertex 结构。但是,我需要能够在运行时编辑数组,因此不能将其声明为 static constexpr

有没有人知道这里可能发生了什么?

最佳答案

您应该通过 new 创建数组,而无需初始化其元素。当您通过初始化在堆上创建数组时,编译器需要在堆栈上准备足够的空间来为数组的多个对象调用构造函数。

看下面的例子(它说明创建带初始化的动态数组是危险的):

struct vertex {
float x,y,z;
vertex() {}
vertex(double x,double y,double z){}
};

int main() {
vertex* v = new vertex[3] {
{1.43,2,3},
{3,4.34,5},
{3,4,5}
};
}
// main function in assembler code
push rbp
mov rbp, rsp
sub rsp, 48 // <--- stack pointer is decresed
mov eax, 36
mov edi, eax
call operator new[](unsigned long)
mov rdi, rax
// call ctors for vertex

asm 代码中最重要的一行是 sub rsp,48。现在我们将数组的大小更改为有 6 个顶点:

vertex* v = new vertex[6] {
{1.43,2,3},
// 4 lines here
{3,4,5}

现在编译器生成 sub rsp, 80 ,如您所见,从堆栈指针中减去的值增加了。

顶点数组越大,从堆栈中占用的空间就越多。堆栈是有限的。这可能就是为什么即使您将数组分配到堆上,您的应用程序也会崩溃。堆栈的所有内存都用于初始化数组的顶点。


我在 https://godbolt.org/ 上编译了这段代码选择了 clang 6.0,没有任何优化。 (启用的优化在输出 asm 代码中发生了很大变化)。当然,其他编译器可能会生成不同的代码,而不是 sub rsp,BIG_VALUE 它们可以分别为每个顶点的 ctor 分 block 占用堆栈空间。

关于c++ - 大型 C++ 数组导致 iOS 上出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53782233/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com