问题描述
我需要帮助弄清楚为什么这段代码会引发读取访问冲突
代码在数组的第4个值处引发读取访问冲突,这是在我在第7和8行中添加动态内存分配时开始发生的
ProceduralStories.cpp
#include <iostream>
#include "ProceduralStories.h"
void main()
{
Object* _objects = NULL;
_objects = new Object[10];
for (int i = 0; i < 10; i++)
{
Object object = Object
{
object.position = glm::vec3 {rand() % 1000 + 1,rand() % 1000 + 1,rand() % 1000 + 1},object.mesh = i
};
_objects[i] = object;
}
Location location1
{
location1.position = glm::vec3 {0.0f,0.0f,0.0f},};
for (int i = 0; i < 10; i++)
{
location1.objects[i] = _objects[i]; //Throws a Read Access Violation at the 4th value of the array,so [3]
std::cout << location1.objects[i].mesh << ",(" << location1.objects[i].position.x << ',' << location1.objects[i].position.y << ',' << location1.objects[i].position.z << ')' << std::endl;
}
}
ProceduralStories.h
#include "glm/vec3.hpp"
struct Object
{
glm::vec3 position;
int mesh;
};
struct Location
{
glm::vec3 position;
Object objects[];
};
解决方法
您从未为objects[]
分配任何空间。因此,当您尝试将location1.objects[i]
设置为某个值时,就是在写入尚未分配的空间。
如果您确实分配了空间,请告诉我分配空间的位置和数量。你做不到。
,请不要这样做。
花时间,学习编写RAII课。
如果您编写新的内容,则必须调用delete,否则会在较大的项目中泄漏内存。
当对象超出范围时,析构函数将为您执行此操作。但是在这种情况下,您将调用默认的析构函数,该默认析构函数仅调用子析构函数,而指针不会自行清除。
#include<iostream>
struct loc{
int pos;
int*obj;
};
void run();
int main(){
run();
return 0;
}
void run()
{
using namespace std;
loc t{ 42,new int[10]};
cout<<t.pos<<endl;
t.obj[0] = 5;
t.obj[9] = 3;
for(int i = 0; i < 10; i++)
{
cout<<t.obj[i]<<endl;
}
delete[] t.obj;
}
编辑:我有责任提供更好的选择。
我不一定认为这是最好的解决方案,但是正如我提到的RAII,我会给你一些东西。
#include<iostream>
class loc{
public:
int pos;
private:
unsigned long size;
int*obj;
public:
loc(): pos{0},size{},obj{nullptr}
{
}
loc(int pos,unsigned long size):pos{pos},size{size}
{
obj = new int[size];
}
loc(loc&)=delete;
loc(loc&&)=delete;
loc operator=(loc&)=delete;
loc operator=(loc&&)=delete;
~loc()
{
delete[] obj;
}
int&operator[](unsigned long index)
{
if(index > size) throw std::out_of_range
( "Index "
+ std::to_string(index)
+ " excededs allocated size "
+ std::to_string(size)
);
return obj[index];
}
};
void run()
{
using namespace std;
loc t{ 42,10};
cout<<t.pos<<endl;
t[0] = 5;
t[9] = 3;
for(int i = 0; i < 10; i++)
{
cout<<t[i]<<endl;
}
// destructor deleate memory for you.
}
请仔细阅读副本移动分配和移动分配构造函数以及何时使用它们。由于这不是个人原因,因此超出了问题的范围。