weird access violation error - c++

I'm getting a (to me) weird run-time access violation error.
I have a class, GUI, that contains a raw pointer to an instance of another class, Crosshair. However, when I try to access that pointer, I get a run-time error! I'm talking about accessing the pointer, I don't even have to dereference it to get the error.
Here's the error:
Unhandled exception at 0x00d4c486 in GPEngine.exe: 0xC0000005: Access violation reading location 0x00000004.
The error returns to this line: int a = (int)m_pCrosshair;
Which is in the GUI::Draw() method, provided below.
EDIT:
I found the problem. It occurred in code I was hiding from you guys, while trying to hide as much irrelevant code as possible... The problem was this:
bool PsychoBots_Game::InitGame()
{
//more code...
return true;
//////GUI
GUIOnIntialisationInfo GUIdesc;
GUIdesc.pContentManager = m_pContentManager;
GUIdesc.pDevice = m_pLevel->GetDevice();
m_pGUI = new GUI(GUIdesc);
}
Pure stupidity, in other words... Sorry for this! I did not write the first part of that method so I wasn't aware of the return values since I never use this when initialising my own stuff...
Old:
Code:
Crosshair.h
#pragma once
#include "D3DUtil.h"
class ContentManager;
class RenderContext;
class Crosshair
{
public:
Crosshair(ID3D10Device* pDevice, ContentManager *pContentManager);
virtual ~Crosshair();
void Draw(ID3D10Device* pDevice, int clientWidth, int clientHeight);
private:
ID3D10InputLayout* m_pVertexLayout;
ID3D10Buffer* m_pVertexBuffer;
ID3D10Effect* m_pDefaultEffect;
ID3D10EffectTechnique* m_pDefaultTechnique;
ID3D10EffectMatrixVariable* m_pWVPVariable;
ID3D10EffectShaderResourceVariable* m_pDiffuseMapVariabele;
ID3D10ShaderResourceView * m_pTextureRV;
private:
//disabled
Crosshair(const Crosshair& b);
Crosshair& operator= (const Crosshair& b);
};
Crosshair.cpp
#include "stdafx.h"
#include "Crosshair.h"
#include "ContentManager.h"
#include "RenderContext.h"
#include "vertex.h"
Crosshair::Crosshair(ID3D10Device* pDevice, ContentManager *pContentManager)
:m_pVertexLayout(nullptr)
,m_pVertexBuffer(nullptr)
,m_pDefaultEffect(nullptr)
,m_pDefaultTechnique(nullptr)
,m_pWVPVariable(nullptr)
,m_pDiffuseMapVariabele(nullptr)
,m_pTextureRV(nullptr)
{
//////Load Texture
m_pTextureRV = pContentManager->GetTexture(pDevice, _T("GUI/Crosshair.png"));
//////Load Effect & Technique
m_pDefaultEffect = pContentManager->GetEffect(pDevice, _T("Effect/Texture2D.fx"));
//get technique
m_pDefaultTechnique = m_pDefaultEffect->GetTechniqueByIndex(0);
if(!m_pDefaultTechnique->IsValid())
{
MessageBox(0,_T("Technique not valid"),_T("ERROR"),0);
exit(-1);
}
//////Get Effect Variables
m_pDiffuseMapVariabele = m_pDefaultEffect->GetVariableBySemantic("DiffuseMap")->AsShaderResource();
if(!m_pDiffuseMapVariabele->IsValid()) {
MessageBox(0,_T("Getting EffectVariable m_pDiffuseMapVariabele Failed"),_T("ERROR"),0);
exit(-1);
}
m_pWVPVariable = m_pDefaultEffect->GetVariableBySemantic("WVP")->AsMatrix();
if(!m_pWVPVariable->IsValid()) {
MessageBox(0,_T("Getting EffectVariable m_pWVPVariable Failed"),_T("ERROR"),0);
exit(-1);
}
//////Define InputLayout
D3D10_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 }
};
UINT numElements = sizeof(layout)/sizeof(layout[0]);
// Create the input layout
D3D10_PASS_DESC PassDesc;
// Get the pass decriptor from the effect technique
m_pDefaultTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc );
HR(pDevice->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &m_pVertexLayout ));
//////Build Vertexbuffer
VertexPosTex v[4];
v[0].pos = D3DXVECTOR3(-0.5f, -0.5f, 0.0f); v[0].tex.x = 0.0f; v[0].tex.y = 1.0f;
v[1].pos = D3DXVECTOR3(-0.5f, 0.5f, 0.0f); v[1].tex.x = 0.0f; v[1].tex.y = 0.0f;
v[2].pos = D3DXVECTOR3( 0.5f, -0.5f, 0.0f); v[2].tex.x = 1.0f; v[2].tex.y = 1.0f;
v[3].pos = D3DXVECTOR3( 0.5f, 0.5f, 0.0f); v[3].tex.x = 1.0f; v[3].tex.y = 0.0f;
//fill a buffer description to copy the vertexdata into graphics memory
D3D10_BUFFER_DESC bd = {};
bd.Usage = D3D10_USAGE_DEFAULT;
bd.ByteWidth = sizeof( VertexPosTex ) * sizeof(v);
bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
bd.MiscFlags = 0;
D3D10_SUBRESOURCE_DATA initData;
initData.pSysMem = v;
//create a ID3D10Buffer in graphics memory containing the vertex info
HR(pDevice->CreateBuffer( &bd, &initData, &m_pVertexBuffer ));
}
Crosshair::~Crosshair()
{
m_pVertexLayout->Release();
m_pVertexBuffer->Release();
}
void Crosshair::Draw(ID3D10Device* pDevice, int clientWidth, int clientHeight)
{
//////Set the input layout
pDevice->IASetInputLayout( m_pVertexLayout );
//more code...
}
GUI.h
#pragma once
#include "D3DUtil.h"
#include "GUIOnInitialisationInfo.h"
#include "GUIPerFrameInfo.h"
#include "GUIPerTickInfo.h"
#include "Crosshair.h"
class GUI
{
public:
virtual ~GUI();
GUI(const GUIOnIntialisationInfo& info);
void Tick(const GUIPerTickInfo& info);
void Draw(const GUIPerFrameInfo& info);
private:
Crosshair* m_pCrosshair;
};
GUI.cpp
#include "stdafx.h"
#include "GUI.h"
GUI::GUI(const GUIOnIntialisationInfo& info)
:m_pCrosshair(new Crosshair(info.pDevice, info.pContentManager))
{
}
GUI::~GUI()
{
delete m_pCrosshair;
}
void GUI::Tick(const GUIPerTickInfo& info)
{
}
void GUI::Draw(const GUIPerFrameInfo& info)
{
int a = (int)m_pCrosshair;
m_pCrosshair->Draw(info.pDevice, info.clientWidth, info.clientHeight);
}
The error returns to this line: int a = (int)m_pCrosshair;
When I delete this line: it will break at m_pCrosshair->Draw(info.pDevice, info.clientWidth,info.clientHeight);
With error: Unhandled exception at 0x001fc49a in GPEngine.exe: 0xC0000005: Access violation reading location 0x00000004
Here is how an instance of GUI is intantiated in my application:
class PsychoBots_Game : public D3DApp
{
//more code...
private:
GUI* m_pGUI;
//more code...
};
(please don't ask me why I have an InitGame() method, we have to do this to make our teachers happy [lol])
bool PsychoBots_Game::InitGame()
{
//////GUI
GUIOnIntialisationInfo GUIdesc;
GUIdesc.pContentManager = m_pContentManager;
GUIdesc.pDevice = m_pLevel->GetDevice();
m_pGUI = new GUI(GUIdesc);
}
And finally, WinMain:
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
TCHAR* cmdLine, int showCmd)
{
PsychoBots_Game *pGameApp= new PsychoBots_Game(hInstance);
if(pGameApp->InitApp())pGameApp->Run();
delete pGameApp;
}
Can anyone tell me what is causing the problem? If by any chance you still need more code, just ask in a comment :)
Thanks

There is a dereference in your class, but one you don't see: m_pCrosshair is a member, so any access will go through the this pointer, which seems to be 0 according to the error. I can't find the invocation site of GUI::Draw, but the instance pointer there is 0 or uninitialized.

Your bool PsychoBots_Game::InitGame() does not return value.
Are you sure that Draw method is being called on m_pGUI?
Are your sure PsychoBots_Game::InitGame() is being called ? From the code your provided only pGameApp->InitApp() is called. m_pGUI is initialized in InitGame.

The class class GUI does not obey the rule of three (while containing a RAW pointer).
Thus you probably have made a copy of the object and the original object got deleted thus leaving you with an object with an invalid pointer.
There is an easy way to check if this is the problem: Make the copy constructor and assignment operator if GUI private if you get a compile time error then this is your problem.
As a side note your code contains way to many RAW pointers.
You should take a look what really needs to be pointers and what can be normal objects. In places where you must have pointers then look at using smart pointers.

Related

How to return float32 array from c++ in node-addon-api?

I am trying to run c++ in node.js using node-addon-api.
I've read one well-written elaborate article from medium.
But I want to pass to one of my functions a float, and a float array to another function.
I want to return a float array from both of them.
The example of a function (greeting.cpp)
#include <iostream>
#include <string>
#include <cmath>
#include "greeting.h"
float* helloUser( float name ) {
float* result = new float[3];
result[0] = 1;
result[1] = 2;
result[2] = name;
return result;
}
And the code of index.cpp with a native implementation of the module:
#include <napi.h>
#include <string>
#include "greeting.h"
Napi::Float32Array greetHello(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
float user = (float) info[0].ToNumber();
float* result = helloUser( user );
return Napi::Float32Array::New(env, result);
}
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set(
Napi::String::New(env, "greetHello"), // property name => "greetHello"
Napi::Function::New(env, greetHello) // property value => `greetHello` function
);
return exports;
}
NODE_API_MODULE(greet, Init)
The thing is, Napi::Float32Array doesn't work, I tried Napi::TypedArrayOf<float>, it doesn't work either. I am not that much into writing modules.
I just want my pure c++ code running in node to send its result to the frontend.
I tried accepting and returning floats with Napi::Number and it works fine.
But I have no clue how to get it start working with arrays.
Any help is appreciated.
I ran into a similar issue and the Napi instance methods expect either a:
void MethodName(const Napi::CallbackInfo& info);
or
Napi::Value MethodName(const Napi::CallbackInfo& info);
Even though Napi::TypedArray inherits from Napi::Object which inherits from Napi::Value, it turns out you have to explicitly return a Napi::Value as follows:
Napi::Value greetHello(Napi::CallbackInfo const& info)
{
Napi::Float32Array arr = Napi::Float32Array::New(info.Env(), 16);
arr[0] = 1;
arr[15] = 16;
return arr;
}
Which will get you a Float32Array:
{
greetHello: [Function (anonymous)]
}
Float32Array(16) [
1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 16
]

DirectX 11 Shader Reflection: Need help setting Constant Buffers variables by name

I'm creating a system that allows the manipulation of constant buffer variables by name using their byte offsets and byte sizes via Shader Reflection. I can bind the buffers to the Device Context just fine, but none of the cubes in my 3D scene are showing up. I believe this is because something is wrong with how I'm mapping data to the Constant Buffers. I cast the struct, be it a float4 or a matrix to a void pointer, and then copy that void pointer data to a another structure that has the variable's name. Once the shader needs to have its buffers updated before a draw call, I map the data of every structure in the list during the Map/Unmap call with a pointer iterator. Also, there seems to be a crash whenever the program calls the destructor on one of the shader constant structures. Below is the code i've written so far:
I'm mapping the buffer data through this algorithm here:
void DynamicConstantBuffer::UpdateChanges(ID3D11DeviceContext* pDeviceContext)
{
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr = pDeviceContext->Map(m_Buffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(hr)) return;
// Set mapped data
for (const auto& constant : m_BufferConstants)
{
char* startPosition = static_cast<char*>(mappedResource.pData) + constant.desc.StartOffset;
memcpy(startPosition, constant.pData, sizeof(constant.pData));
}
// Copy memory and unmap
pDeviceContext->Unmap(m_Buffer.Get(), 0);
}
I'm initializing the Constant Buffer here:
BOOL DynamicConstantBuffer::Initialize(UINT nBufferSlot, ID3D11Device* pDevice, ID3D11ShaderReflection* pShaderReflection)
{
ID3D11ShaderReflectionConstantBuffer* pReflectionBuffer = NULL;
D3D11_SHADER_BUFFER_DESC cbShaderDesc = {};
// Fetch constant buffer description
if (!(pReflectionBuffer = pShaderReflection->GetConstantBufferByIndex(nBufferSlot)))
return FALSE;
// Get description
pReflectionBuffer->GetDesc(&cbShaderDesc);
m_BufferSize = cbShaderDesc.Size;
// Create constant buffer on gpu end
D3D11_BUFFER_DESC cbDescription = {};
cbDescription.Usage = D3D11_USAGE_DYNAMIC;
cbDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cbDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
cbDescription.ByteWidth = cbShaderDesc.Size;
if (FAILED(pDevice->CreateBuffer(&cbDescription, NULL, m_Buffer.GetAddressOf())))
return FALSE;
// Poll shader variables
for (UINT i = 0; i < cbShaderDesc.Variables; i++)
{
ID3D11ShaderReflectionVariable* pVariable = NULL;
pVariable = pReflectionBuffer->GetVariableByIndex(i);
// Get variable description
D3D11_SHADER_VARIABLE_DESC variableDesc = {};
pVariable->GetDesc(&variableDesc);
// Push variable back into list of variables
m_BufferConstants.push_back(ShaderConstant(variableDesc));
}
return TRUE;}
Here's the method that sets a variable within the constant buffer:
BOOL DynamicConstantBuffer::SetConstantVariable(const std::string& varName, const void* varData)
{
for (auto& v : m_BufferConstants)
{
if (v.desc.Name == varName)
{
memcpy(v.pData, varData, sizeof(varData));
bBufferDirty = TRUE;
return TRUE;
}
}
// No variable to assign :(
return FALSE;
}
Here's the class layout for ShaderConstant:
class ShaderConstant
{
public:
ShaderConstant(D3D11_SHADER_VARIABLE_DESC& desc)
{
this->desc = desc;
pData = new char[desc.Size];
_size = desc.Size;
};
~ShaderConstant()
{
if (!pData)
return;
delete[] pData;
pData = NULL;
}
D3D11_SHADER_VARIABLE_DESC desc;
void* pData;
size_t _size;
};
Any help at all would be appreciated. Thank you.

Vulkan's VkImageView and VkImage objects causing unhandled excecption within the SwapChain

I'm following vulkan-tutorial and I've successfully rendered a spinning square. I'm at the point in the lessons right before applying textures. Before moving on within the lessons, I've been modularizing the code into a framework of interfaces one piece at a time. I have successfully managed to extract various Vulkan objects out of the main engine class into their own classes. Each of these class objects has an interface with an initialize, create, and cleanup function at a minimum.
I've done this with a Buffer class that is an abstract base class that my IndexBuffer, VertexBuffer, and UniformBuffer all derived from. I've done this with my CommandPool class, SyncObjects(VkSemaphore and VkFence) classes, my Pipelines(only MainGraphicsPipeline for now), and my SwapChain.
With all of these in their own classes, I'm now storing these classes as either shared_ptr<Class> or vector<shared_ptr<Class>> within my classes that have internal instances of these. This is the design flow that I've been staying with.
Everything was working perfectly fine until I started to have VkImageView types contained within their own class. Within my SwapChainclass it contained the private member:
std::vector<VkImageView> imageViews_
and these member functions that work on them:
void SwapChain::cleanupImageViews() {
for (auto imageView : imageViews_) {
vkDestroyImageView(*device_, imageView, nullptr);
}
}
void SwapChain::createImageViews() {
imageViews_.resize(images_.size());
for (size_t i = 0; i < images_.size(); i++) {
VkImageViewCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = images_[i];
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = imageFormat_;
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.baseMipLevel = 0;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1;
if (vkCreateImageView(*device_, &createInfo, nullptr, &imageViews_[i]) != VK_SUCCESS) {
throw std::runtime_error("failed to create image views!");
}
}
}
With my code in this state, everything works fine. I'm able to render a spinning colored square, I can resize the window and close the window with 0 errors from both Visual Studio and from Vulkan Layers.
When I change to this pattern that I've done before:
std::vector<std::shared_ptr<ImageView>> imageViews_;
and my functions become:
void SwapChain::cleanupImageViews() {
for (auto& imageView : imageViews_ ) {
imageView->cleanup();
}
}
void SwapChain::createImageViews() {
imageViews_.resize(images_.size());
for(auto& i : imageViews_) {
i = std::shared_ptr<ImageView>();
i->initialize(device_);
}
for (size_t i = 0; i < images_.size(); i++ ) {
imagesViews_[i]->create(images_[i], imageFormat_);
}
}
It fails when It calls the create() for the ImageViews giving me an unhandled exception: access read/write violation stating that the "this" pointer within my ImageView class is nullptr.
Here is what my ImageView class looks like:
ImageView.h
#pragma once
#include "utility.h"
namespace ForceEngine {
namespace vk {
class ImageView {
private:
VkImageView imageView_;
VkDevice* device_;
VkImage image_;
VkFormat format_;
public:
ImageView() = default;
~ImageView() = default;
void initialize(VkDevice* device);
void create(VkImage image, VkFormat format);
void cleanup();
VkImageView* get() { return &imageView_; }
private:
void createImageView();
};
} // namespace vk
} // namespace ForceEngine
ImageView.cpp
#include "ImageView.h"
namespace ForceEngine {
namespace vk {
void ImageView::initialize(VkDevice* device) {
if (device == nullptr) {
throw std::runtime_error("failed to initialize ImageView: device was nullptr!");
device_ = device;
}
}
void ImageView::create(VkImage image, VkFormat format) {
//if (image == nullptr) throw std::runtime_error("failed to create Image View: image was nullptr!");
//if (format == nullptr) throw std::runtime_error("failed to create Image View: format was nullptr!");
image_ = image; // This is where it is throwing the exception.
format_ = format;
createImageView();
}
void ImageView::createImageView() {
VkImageViewCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = image_;
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = format_;
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.baseMipLevel = 0;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1;
if (vkCreateImageView(*device_, &createInfo, nullptr, &imageView_) != VK_SUCCESS) {
throw std::runtime_error("failed to create image views!");
}
}
void ImageView::cleanup() {
vkDestroyImageView(*device_, imageView_, nullptr);
}
} // namespace vk
} // namespace ForceEngine
Within my class, I've tried having image_ as a pointer and as a non-pointer and as for the signature of create(), I've tried passing the parameters by copy, reference, pointer, const reference, const pointer, etc. and to no avail, none of the above has worked. Everything keeps causing an exception. I don't know what's causing the access violation. For some reason, the ImageView class is not properly allocating memory for the image_ member as it states that this was nullptr for this class or it can't write to memory, etc. Yet, I've followed this same pattern for all of my other Vulkan Objects and did not have this issue until now.
What are the takes on the usages and proper setup of VkImageView and VkImage within the context of the SwapChain? Currently, the VkImages are still stored within the SwapChain as std::vector<VkImage> I can create it successfully within the class directly, but when I try to extract the VkImageView out into its own class object is when I start to run into this problem. I'm learning Vulkan through this tutorial and I'm starting to get a grasp of how it is designed, but I'm still no expert at the API. Right now any help would be appreciated. And, yes I've stepped through the debugger, I've watched my variables, I've watched the call stack, and for the life of me, I'm completely stumped. If you need more information than this please don't hesitate to ask.
User nicol-bolas pointed out in the comment section that I had i = std::shared_ptr<ImageView>() and that I should have had i = std::make_shared<ImageView>() and yes that is correct and that is how my other independent classes are being created. This was an overlooked typo mistake. So I give credit to NicolBolas for that. However, after fixing that bug, it allowed me to find and fix the real bug.
The actual bug that was causing the Unhandled Exception had nothing to do with the ImageView, VkImageView, VkImage objects. The real culprit was within the ImageView class itself within its initialize() method. I was assigning its member device_ within the scope of the if statement, where I was checking to see if the device pointer being passed in was nullptr or not.
I originally had this:
void ImageView::initialize(VkDevice* device) {
if (device == nullptr) { throw std::runtime_error("failed to initialize Image View: device was nullptr!");
device_ = nullptr;
}
}
And the device_ was never being set. It should have been:
void ImageView::initialize(VkDevice* device) {
if (device == nullptr) throw std::runtime_error("failed to initialize Image View: device was nullptr!");
device_ = nullptr;
}
Now the code works again and I have a spinning colored square. The code exits with 0 errors and no messages from Vulkan Layers.
I had simply overlooked the {} within the if statement of the function.

0xC0000005: Access violation reading location of an Integer?

It seems normally people receive these errors when working with pointers, array, structs, etc. I'm getting it on every integer in a class, which confuses me. I'm sure I'm just missing some small technical detail (I'm a bit new to this).
The exact error is:
First-chance exception at 0x003e6616 in Mine.exe: 0xC0000005:
Access violation reading location 0x00000008.
Unhandled exception at 0x003e6616 in Mine.exe: 0xC0000005:
Access violation reading location 0x00000008.
The code breaks at the first line in this class method:
void Grid::Move(int x, int y)
{
this->offX+=x;
this->offY+=y;
for (int i=0;i<2;i++)
for (int k=0;k<2;k++)
BitmapSetxy(chunks[i][k]->map,this->offX,this->offY);
}
Here is the constructor of Grid:
Grid::Grid()
{
totalW =320*2;
totalH = 320*2;
offX = 0;
offY = 0;
//Fill the chunks array with Maps to be used
for (int i=0;i<2;i++)
for (int k=0;k<2;k++)
chunks[i][k] = new Map(i*320,k*320);
//Everything starts as dirt
for (int x=0;x<(320*2)/20;x++)
for (int y=0;y<(320*2)/20;y++)
blocks[x][y] = bType::Dirt;
}
And the header file:
#ifndef MapDef
#define MapDef
#include "Map.h"
class Grid
{
private:
int totalW, totalH;
int offX, offY;
public:
enum bType
{
Blank,
Dirt,
Copper
};
Map * chunks[2][2];
bType blocks[32][48];
void RemoveBlock(int x, int y);
bType GetBlockAt(int x, int y);
int GetAbsolutePosition20(int);
int GetMapIndex(int);
int GetChunkRelative(int,int);
bType GetBlockBelow(int x, int y);
bType GetBlockAbove(int x, int y);
bType GetBlockSide(int x, int y, bool isRight);
void Move(int x, int y);
Grid();
};
#endif
When looking at the locals view of the current instance of Grid totalW, totalH, offX,offY all show the CXX0030 error, but the two arrays are perfectly fine. What exactly is going on here?
EDIT:
The definition of the grid pointer is stored in a separate little namespace that serves as something of a static class:
namespace Engine
{
static Grid * grid;
static Player * player;
}
It is actually created here in the main cpp file:
//Initialize engine
Engine::grid = new Grid();
Engine::player = new Player(160,240);
Here is the excerpt where it is called, in another class called Player
if (y>392 && y<480 && x>75 && x<152)
{
printf("Right");
Engine::grid->Move(20,0);
}
Edit 2:
I'm sorry, I forgot to remove the "static" keyword from the grid declaration in engine. I believe that was what was causing the problem.
According to the error message, your code is trying to access address 0x00000008, which is very close to 0. This means you probably have a null pointer of type Grid * somewhere and you are calling a function on it.
You should either ensure that the pointer is not null, or check it. For example:
Grid * grid = ...;
if (grid == NULL){ return; }
grid->move(0,1);
Note that NULL is the same as 0.
What is the value of 'this'? Are you trying to dereference a null pointer to an instance of Grid?

Code requires too much memory

I'm porting some code to another structure:
class EnvironObject
{
protected:
vector<float> mX, mY, mXSpeed, mYSpeed;
int mMaxObjects;
public:
virtual void init(int maxObjects);
virtual void setLimit(int limit);
virtual int getLimit();
virtual void update(float arg) = 0;
};
void EnvironObject::setLimit(int limit)
{
mMaxObjects = limit;
mX.resize(limit, 0); mY.resize(limit, 0);
mXSpeed.resize(limit, 0); mY.resize(limit, 0);
}
int EnvironObject::getLimit()
{
return mMaxObjects;
}
void EnvironObject::init(int maxObjects)
{
mX = mY = mXSpeed = mYSpeed = std::vector<float>(mMaxObjects);
fill(mX.begin(), mX.end(), 0);
fill(mY.begin(), mY.end(), 0);
fill(mXSpeed.begin(), mXSpeed.end(), 0);
fill(mYSpeed.begin(), mYSpeed.end(), 0);
/*mX.reserve(mMaxObjects * 1.5); mY.reserve(mMaxObjects * 1.5);
mXSpeed.reserve(mMaxObjects * 1.5); mYSpeed.reserve(mMaxObjects * 1.5);*/
mMaxObjects = maxObjects;
}
This is some basic class, now it's usage:
class Rain : public EnvironObject
{
public:
Rain(int maxDrops = 150);
void update(float windPower);
};
Rain::Rain(int maxDrops)
{
srand(time(NULL));
IEnvironObject::init(maxDrops);
}
void Rain::update(float windPower)
{
for (int i=0; i < mMaxObjects; i++)
{
mX[i] += mXSpeed[i];
mY[i] += mYSpeed[i];
mXSpeed[i] += windPower;
mYSpeed[i] += G;
// Drawing
}
}
The objects Rain creates with default constructor (so, each array is 150 elements size) and then I'm calling setLimit(50).
The problem is that code fails almost each running with exception:
terminate called after throwing an instance of 'std::bad_alloc'
And sometimes it segfaults at line:
mY[i] += mYSpeed[i];
I can't image what could it be, because the code is old and it worked. The new one is only base class.
And when I'm looking at RAM usage when starting app, I see almost +600 mb!
Look again at that function of yours:
void EnvironObject::init(int maxObjects)
{
mX = mY = mXSpeed = mYSpeed = std::vector<float>(mMaxObjects);
// ^
// ...
mMaxObjects = maxObjects;
}
You're using a not yet initialized variable.
A big problem with your class is that you are doing what's called two-phase construction. Your class EnvironObject has a compiler-supplied default constructor that creates an object with random values for all POD types (mMaxObjects). Users then need to call the init() method to really initialize the object. But that's what constructors are there for!
void EnvironObject::EnvironObject(int maxObjects)
: mMaxObjects(maxObjects)
, mX(maxObjects), mY(maxObjects), mXSpeed(maxObjects), mYSpeed(maxObjects)
{
/* these aren't necessary, std::vector automatically does this
fill(mX.begin(), mX.end(), 0);
fill(mY.begin(), mY.end(), 0);
fill(mXSpeed.begin(), mXSpeed.end(), 0);
fill(mYSpeed.begin(), mYSpeed.end(), 0);
*/
}
Derived classes can then use this constructor:
Rain::Rain(int maxDrops)
: EnvironObject(maxDrops)
{
srand(time(NULL));
}
Regarding this crash in the subscription mY[i] += mYSpeed[i]:
This might happen when you are calling this function through a pointer that's pointing to nowhere.
You're using mMaxObjects in init() before initializing it. So it has a random value.
void EnvironObject::init(int maxObjects)
{
mX = mY = mXSpeed = mYSpeed = std::vector<float>(mMaxObjects); // you mean maxObjects here
I think you want to replace
void EnvironObject::init(int maxObjects)
{
mX = mY = mXSpeed = mYSpeed = std::vector<float>(mMaxObjects);
with
void EnvironObject::init(int maxObjects)
{
mX = mY = mXSpeed = mYSpeed = std::vector<float>(maxObjects);
Notice the replacement of mMaxObject to maxObjects in the vector creation.
One comment, though it won't likely fix your memory error, is that since the fields mX, mY, mXSpeed, and mYSpeed seem related and the vectors are all the same size, you should consider merging them into one structure with four members, and having a single vector containing several of those structure instances.