C++ 向量读取访问冲突 Mylast 返回 0x8
C++ Vector read access violation Mylast returned 0x8
我真的需要这方面的帮助,因为我非常困惑,不知道该怎么做。
编辑:
你们很多人都说我需要使用调试器,但让我明确一点,我已经很长时间没有使用 C++ 了,我总共使用了 visual studio 2几周所以我不知道它可以用调试器做的所有很酷的事情。
我是一名大学二年级的学生,主要是通过失败来想办法做某事。
我不是专业的编码员,在涉及这些问题时我不具备你们所拥有的所有知识,这就是我问这个问题的原因。我正在尽力展示我的问题,所以是的,我的代码包含很多错误,因为我对很多 C++ 原则只有非常基本的了解,所以请在评论时记住这一点
我在这里 post 只是因为我不知道现在还能问谁。
我有一个名为 world 的函数,它应该调用我的渲染 class 以将其矢量内的所有对象绘制到屏幕上。
#include "C_World.h"
C_World::C_World()
{
// creates an instance of the renderer class to render any drawable objects
C_Renderer *render = new C_Renderer;
}
C_World::~C_World()
{
delete[] render;
}
// adds an object to the world vector
void C_World::addToWorld(C_renderable* a)
{
world_list.push_back(a);
}
void C_World::World_Update()
{
render->ClearScreen();
World_Render();
}
void C_World::World_Render() {
for (int i = 0; i < 1; i++)
{
//render->DrawSprite(world_list[i]->getTexture(), world_list[i]->get_X, world_list[i]->get_Y());
render->DrawSprite(1, 1, 1);
}
}
在测试时,我注释掉了 Sprites get 函数,以检查它们是否导致了问题。
renderer sprites通过create sprite函数添加到constructor中的vector list
C_Renderer::C_Renderer()
{
// test sprite: Id = 1
CreateSprite("WhiteBlock.png", 250, 250, 1);
}
我认为这可能是问题所在,所以我在其他函数中使用了它,但这并没有解决任何问题
这里是绘制和创建 Sprite 函数
// Creates a sprite that is stored in the SpriteList
// Sprites in the spriteList can be used in the drawSprite function
void C_Renderer::CreateSprite(std::string texture_name,
unsigned int Texture_Width, unsigned int Texture_height, int spriteId)
{
C_Sprite *a = new C_Sprite(texture_name,Texture_Width,
Texture_height,spriteId);
SpriteList.push_back(a);
size_t b = SpriteList.size();
HAPI.DebugText(std::to_string(b));
}
// Draws a sprite to the X and Y co-ordinates
void C_Renderer::DrawSprite(int id,int x,int y)
{
Blit(screen, _screenWidth, SpriteList[id]->get_Texture(),
SpriteList[id]->getTexture_W(), SpriteList[id]->getTexture_H(), x, y);
}
我什至在创建精灵函数中添加了一些测试代码来检查精灵是否被添加到矢量列表中。它 returns 1 所以我认为它是。
Exception thrown: read access violation.
std::_Vector_alloc<std::_Vec_base_types<C_Sprite *,
std::allocator<C_Sprite *> > >::_Mylast(...) returned 0x8.
这是我从编译器得到的完整错误
如果您需要更多信息,我真的很困惑,请直接说出来post
编辑 2:
#pragma once
#include <HAPI_lib.h>
#include <vector>
#include <iostream>
#include "C_renderable.h"
#include "C_Renderer.h"
class C_World
{
public:
C_World();
~C_World();
C_Renderer *render = nullptr;
void World_Update();
void addToWorld(C_renderable* a);
private:
std::vector<C_renderable*> world_list;
void C_World::World_Render();
};
#pragma once
#include <HAPI_lib.h>
#include "C_renderable.h"
#include "C_Sprite.h"
#include <vector>
class C_Renderer
{
public:
C_Renderer();
~C_Renderer();
// gets a pointer to the top left of screen
BYTE *screen = HAPI.GetScreenPointer();
void Blit(BYTE *destination, unsigned int destWidth,
BYTE *source, unsigned int sourceWidth, unsigned int sourceHeight,
int posX, int posY);
void C_Renderer::BlitBackground(BYTE *destination,
unsigned int destWidth, unsigned int destHeight, BYTE *source,
unsigned int sourceWidth, unsigned int sourceHeight);
void SetPixel(unsigned int x,
unsigned int y, HAPI_TColour col,BYTE *screen, unsigned int width);
unsigned int _screenWidth = 1750;
void CreateSprite(std::string texture_name,
unsigned int Texture_Width,unsigned int Texture_height, int spriteId);
void DrawSprite(int id, int x, int y);
void ClearScreen();
private:
std::vector<C_Sprite*> SpriteList;
};
我不是随便说的,但是您显示的代码绝对糟糕。在您对 C++ 的理解中,您需要停下来返回 几个 级别。
很可能,您的崩溃是您的一个或多个函数中的一个简单 "shadowing" 问题的结果:
C_World::C_World()
{
// creates an instance of the renderer class to render any drawable objects
C_Renderer *render = new C_Renderer;
}
C_World::~C_World()
{
delete[] render;
}
这里有 多个 错误,你没有显示 C_World
的定义,但如果这段代码编译通过,我们可以推断它有一个成员 render
,你掉进了一个常见的陷阱。
C_Renderer *render = new C_Renderer;
因为这一行以 type 开头,所以这是一个新的局部变量 render
的 definition。你的编译器应该警告你这个shadows同名的class范围变量。
这几行代码是什么
C_World::C_World()
{
// creates an instance of the renderer class to render any drawable objects
C_Renderer *render = new C_Renderer;
}
做的是:
. assign an undefined value to `this->render`,
. create a *local* variable `render`,
. construct a dynamic `C_Renderer` presumably on the heap,
. assign that to the *local* variable `render`,
. exit the function discarding the value of `render`.
所以此时内存不再被跟踪,它已经泄漏,this->render
指向一个未定义的值。
您在几个函数中重复这个问题,将 new
结果分配给局部变量并且不对它们进行任何操作。导致问题的可能不是这个特定问题实例。
你的下一个问题是 new/delete 与 new[]/delete[] 不匹配:
C_World::~C_World()
{
delete[] render;
}
这将导致未定义的行为:this->render
未定义,并且 delete[]
在非新 [] 分配上未定义。
大多数程序员使用将成员变量与局部变量区分开来的命名约定。两种常见的做法是成员的 m_
前缀或 _
后缀,例如
class C_World
{
public:
C_Foo* m_foo; // option a
C_Renderer* render_; // option b
// ...
}
也许你应该考虑使用现代 C++ 的智能指针概念:
#include <memory>
class C_World {
// ...
std::unique_ptr<C_Renderer> render_;
// ...
};
C_World::C_World()
: render_(new C_Renderer) // initializer list
{}
但不清楚您为什么首先要在这里使用动态分配。好像实例成员会更好:
class C_World {
C_Renderer render_;
};
C_World::C_World() : render_() {}
我真的需要这方面的帮助,因为我非常困惑,不知道该怎么做。
编辑:
你们很多人都说我需要使用调试器,但让我明确一点,我已经很长时间没有使用 C++ 了,我总共使用了 visual studio 2几周所以我不知道它可以用调试器做的所有很酷的事情。
我是一名大学二年级的学生,主要是通过失败来想办法做某事。
我不是专业的编码员,在涉及这些问题时我不具备你们所拥有的所有知识,这就是我问这个问题的原因。我正在尽力展示我的问题,所以是的,我的代码包含很多错误,因为我对很多 C++ 原则只有非常基本的了解,所以请在评论时记住这一点
我在这里 post 只是因为我不知道现在还能问谁。
我有一个名为 world 的函数,它应该调用我的渲染 class 以将其矢量内的所有对象绘制到屏幕上。
#include "C_World.h"
C_World::C_World()
{
// creates an instance of the renderer class to render any drawable objects
C_Renderer *render = new C_Renderer;
}
C_World::~C_World()
{
delete[] render;
}
// adds an object to the world vector
void C_World::addToWorld(C_renderable* a)
{
world_list.push_back(a);
}
void C_World::World_Update()
{
render->ClearScreen();
World_Render();
}
void C_World::World_Render() {
for (int i = 0; i < 1; i++)
{
//render->DrawSprite(world_list[i]->getTexture(), world_list[i]->get_X, world_list[i]->get_Y());
render->DrawSprite(1, 1, 1);
}
}
在测试时,我注释掉了 Sprites get 函数,以检查它们是否导致了问题。
renderer sprites通过create sprite函数添加到constructor中的vector list
C_Renderer::C_Renderer()
{
// test sprite: Id = 1
CreateSprite("WhiteBlock.png", 250, 250, 1);
}
我认为这可能是问题所在,所以我在其他函数中使用了它,但这并没有解决任何问题
这里是绘制和创建 Sprite 函数
// Creates a sprite that is stored in the SpriteList
// Sprites in the spriteList can be used in the drawSprite function
void C_Renderer::CreateSprite(std::string texture_name,
unsigned int Texture_Width, unsigned int Texture_height, int spriteId)
{
C_Sprite *a = new C_Sprite(texture_name,Texture_Width,
Texture_height,spriteId);
SpriteList.push_back(a);
size_t b = SpriteList.size();
HAPI.DebugText(std::to_string(b));
}
// Draws a sprite to the X and Y co-ordinates
void C_Renderer::DrawSprite(int id,int x,int y)
{
Blit(screen, _screenWidth, SpriteList[id]->get_Texture(),
SpriteList[id]->getTexture_W(), SpriteList[id]->getTexture_H(), x, y);
}
我什至在创建精灵函数中添加了一些测试代码来检查精灵是否被添加到矢量列表中。它 returns 1 所以我认为它是。
Exception thrown: read access violation.
std::_Vector_alloc<std::_Vec_base_types<C_Sprite *,
std::allocator<C_Sprite *> > >::_Mylast(...) returned 0x8.
这是我从编译器得到的完整错误
如果您需要更多信息,我真的很困惑,请直接说出来post
编辑 2:
#pragma once
#include <HAPI_lib.h>
#include <vector>
#include <iostream>
#include "C_renderable.h"
#include "C_Renderer.h"
class C_World
{
public:
C_World();
~C_World();
C_Renderer *render = nullptr;
void World_Update();
void addToWorld(C_renderable* a);
private:
std::vector<C_renderable*> world_list;
void C_World::World_Render();
};
#pragma once
#include <HAPI_lib.h>
#include "C_renderable.h"
#include "C_Sprite.h"
#include <vector>
class C_Renderer
{
public:
C_Renderer();
~C_Renderer();
// gets a pointer to the top left of screen
BYTE *screen = HAPI.GetScreenPointer();
void Blit(BYTE *destination, unsigned int destWidth,
BYTE *source, unsigned int sourceWidth, unsigned int sourceHeight,
int posX, int posY);
void C_Renderer::BlitBackground(BYTE *destination,
unsigned int destWidth, unsigned int destHeight, BYTE *source,
unsigned int sourceWidth, unsigned int sourceHeight);
void SetPixel(unsigned int x,
unsigned int y, HAPI_TColour col,BYTE *screen, unsigned int width);
unsigned int _screenWidth = 1750;
void CreateSprite(std::string texture_name,
unsigned int Texture_Width,unsigned int Texture_height, int spriteId);
void DrawSprite(int id, int x, int y);
void ClearScreen();
private:
std::vector<C_Sprite*> SpriteList;
};
我不是随便说的,但是您显示的代码绝对糟糕。在您对 C++ 的理解中,您需要停下来返回 几个 级别。
很可能,您的崩溃是您的一个或多个函数中的一个简单 "shadowing" 问题的结果:
C_World::C_World()
{
// creates an instance of the renderer class to render any drawable objects
C_Renderer *render = new C_Renderer;
}
C_World::~C_World()
{
delete[] render;
}
这里有 多个 错误,你没有显示 C_World
的定义,但如果这段代码编译通过,我们可以推断它有一个成员 render
,你掉进了一个常见的陷阱。
C_Renderer *render = new C_Renderer;
因为这一行以 type 开头,所以这是一个新的局部变量 render
的 definition。你的编译器应该警告你这个shadows同名的class范围变量。
这几行代码是什么
C_World::C_World()
{
// creates an instance of the renderer class to render any drawable objects
C_Renderer *render = new C_Renderer;
}
做的是:
. assign an undefined value to `this->render`,
. create a *local* variable `render`,
. construct a dynamic `C_Renderer` presumably on the heap,
. assign that to the *local* variable `render`,
. exit the function discarding the value of `render`.
所以此时内存不再被跟踪,它已经泄漏,this->render
指向一个未定义的值。
您在几个函数中重复这个问题,将 new
结果分配给局部变量并且不对它们进行任何操作。导致问题的可能不是这个特定问题实例。
你的下一个问题是 new/delete 与 new[]/delete[] 不匹配:
C_World::~C_World()
{
delete[] render;
}
这将导致未定义的行为:this->render
未定义,并且 delete[]
在非新 [] 分配上未定义。
大多数程序员使用将成员变量与局部变量区分开来的命名约定。两种常见的做法是成员的 m_
前缀或 _
后缀,例如
class C_World
{
public:
C_Foo* m_foo; // option a
C_Renderer* render_; // option b
// ...
}
也许你应该考虑使用现代 C++ 的智能指针概念:
#include <memory>
class C_World {
// ...
std::unique_ptr<C_Renderer> render_;
// ...
};
C_World::C_World()
: render_(new C_Renderer) // initializer list
{}
但不清楚您为什么首先要在这里使用动态分配。好像实例成员会更好:
class C_World {
C_Renderer render_;
};
C_World::C_World() : render_() {}