繁体   English   中英

错误,将对象动态分配给数组

[英]Error, dynamically allocating objects to an array

我有一个指向结构数组的指针,如下所示:

class Terrian  {
     ...
    private:
        Vector *terrian_vertices;
     ...
}

指针的数据在“ construct_vertices”函数中生成

Terrian::Terrian(int width, int height)  {
    this->width = width;
    this->height = height;

    std::cout << "Width: " << width << "  Height: " << height << "\n";

    std::cout << "Vertices\n";
    construct_vertices();
    std::cout << "Element\n";
    construct_elements();
    std::cout << "Buffers\n";
    construct_buffers();
}

void Terrian::construct_vertices()  {
    terrian_vertices = new Vector[width * height];

    std::cout << "Generating data\n";

    for (int x = 0; x < width; x++)  {
        for (int y = 0; y < height; y++)  {
            int index = x + y * width;

            Vector *pos = new Vector((GLfloat)x, 0.0f, (GLfloat)-y);
            memcpy(pos, terrian_vertices, sizeof(Vector) * index);

            std::cout << terrian_vertices[index].x;

            Color *color = new Color(0, 255, 0);
            memcpy(color, terrian_colors, sizeof(Color) * index);
        }
    }
}

这是程序的输出(我在main函数中所做的全部是实例化对象)

Width: 32  Height: 32
Vertices
Generating data
5.2349e-039
Process returned -1073741819 (0xC0000005)   execution time : 10.073 s
Press any key to continue.

当第一个指针复制到数组时,程序崩溃,“ x”的输出应为0。这令人费解。 有谁知道是什么原因导致这种情况发生的? 如果是这样,是否有更好的方法动态分配结构-无需使用memcpy?

有谁知道是什么原因导致这种情况发生的?

memcpy的使用不正确。 任何参考文档都会告诉您。

第一个参数是指向目标的指针,该目标将是terrian_vertices数组的index元素: terrian_vertices + index

第二个参数是指向源的指针pos

(如果您很好奇,那么目的地之所以要比来源更早是因为它与赋值运算符平行: destination = source

第三个参数是要复制的数据量,在您的情况下仅为sizeof(Vector) :它只是需要复制的一个 Vector ,而不是index

像代码一样滥用memcpy容易导致未定义的行为,幸运的是,这表现为错误。

如果是这样,是否有更好的方法动态分配结构-无需使用memcpy?

是。 不要自己管理内存:使用std::vector和常规复制语义。

class Terrian  {
// ...
private:
    std::vector<Vector> terrain_vertices;
    // Hmm, this may need some touch up on naming,
    // or it may get confusing with two "vector" thingies around
};

// ...

void Terrian::construct_vertices()  {
    terrain_vertices.reserve(width * height);
     // reserve is actually optional,
     // but I put it here to parallel the original code
     // and because it may avoid unneeded allocations

    std::cout << "Generating data\n";

    for (int x = 0; x < width; x++)  {
        for (int y = 0; y < height; y++)  {
            terrain_vertices.emplace_back((GLfloat)x, 0.0f, (GLfloat)-y);
            // or this if your compiler doesn't support C++11:
            // terrain_vertices.push_back(Vector((GLfloat)x, 0.0f, (GLfloat)-y));

            std::cout << terrian_vertices[index].x;

            // same thing for colors
            terrain_colors.emplace_back(0, 255, 0);
        }
    }

请注意,现在看不到任何new 这解决了原始代码的另一个问题:每个循环迭代泄漏了一个Vector实例和一个Color实例。

Vector *pos = new Vector((GLfloat)x, 0.0f, (GLfloat)-y);
memcpy(pos, terrian_vertices, sizeof(Vector) * index);

你不能那样做。 newVector分配了足够的内存,并且pos指向那里。 但是,然后继续将sizeof(Vector) * index字节复制到该位置。 由于int index = x + y * width;因此第一次以0字节结尾int index = x + y * width; 是0。下一次是2 * width , which is likely greater than 1 , so you end up copying past * pos`的内容, so you end up copying past到无人区。

附带说明一下,您不应该使用memcpy复制复杂类型。 可能没问题,可能只需要一点点复制,但是如果与某些类型(即,由于内部语义而无法复制的类型,如RAII样式容器)一起使用,这可能对您不利。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM