Branch: mesh_and_render_commands
Review Date: 2026-02-20
Status Key: [ ] Open [⌛] Need more guidance [🚩] Fixed but needs review [✅] Fixed
- File:
engine/source/render/Material.cpp - Status:
[✅] - What: Assigns incoming pointer to
m_shaderProgram, then immediatelydeletes it. Every subsequent call toBind()dereferences freed memory. Also,shaderProgram = nullptronly nulls the local parameter, not the member. - Fix: Remove the two lines
delete shaderProgram;andshaderProgram = nullptr;.
- File:
engine/source/render/RenderQueue.cpp - Status:
[✅] - What:
m_renderCommandsis a fixed-size array declared inside the class (stack memory). Callingdelete[]on it is undefined behaviour. - Fix: Remove the destructor body entirely. The queue does not own Mesh or Material, so nothing inside the array needs to be freed.
- Files:
engine/source/render/RenderQueue.cpp,source/Game.cpp - Status:
[✅] - What:
Game::Update()createsRenderCommand commandon the stack and passes&commandtoSubmit(). The instantUpdate()returns,commandis destroyed.Engine::Run()then callsDraw()and dereferences that dead address — use-after-free crash. - Fix: Change
m_renderCommandsto storeRenderCommandvalues (not pointers). Add a count member.Submittakes by value;Drawiterates up to count and resets it to 0.
- Files:
engine/source/graphics/VertexLayout.h,engine/source/render/Mesh.cpp - Status:
[✅] - What:
VertexLayouthas a destructor (delete[] elements) but no copy constructor or copy assignment operator. The compiler generates shallow copies. InGame::Init(),vertexLayoutis copied intoMeshshallowly; whenInit()ends,vertexLayoutdestructs and deletes the shared array — leavingm_mesh->m_vertexLayout.elementsdangling. - Fix: Add a deep copy constructor and deep copy assignment operator to
VertexLayoutthat allocate a newelementsarray and copy all elements individually.
- File:
engine/source/render/Mesh.h/Mesh.cpp - Status:
[✅] - What:
Meshcreates VAO, VBO, and EBO but never callsglDeleteVertexArrays/glDeleteBuffers. GPU memory leaks on destruction. - Fix: Add
~Mesh()that callsglDeleteVertexArrays(1, &m_VAO),glDeleteBuffers(1, &m_VBO), andglDeleteBuffers(1, &m_EBO)(guard EBO withif (m_EBO != 0)).
- File:
engine/source/render/Material.cpp - Status:
[✅] - What: The destructor that frees
m_shaderProgramis commented out.m_shaderProgramis never deleted. - Fix: Uncomment
~Material(), declare it inMaterial.h.
- File:
source/Game.cpp - Status:
[✅] - What:
m_meshis heap-allocated withnewinInit().Destroy()is empty. Memory leaked on shutdown. - Fix: Add
delete m_mesh; m_mesh = nullptr;insideGame::Destroy().
- File:
engine/source/graphics/GraphicsAPI.cpp—CreateVertexBuffer()andCreateIndexBuffer() - Status:
[✅] - What:
verticesis aconst float*.&verticesis aconst float**— the address of the local stack parameter. The GPU receives the address of a stack variable, not the actual geometry data. - Fix: Change
&vertices→verticesand&indices→indices.
- File:
engine/source/graphics/GraphicsAPI.cpp - Status:
[✅] - What:
vertexShader,fragmentShader, andshaderProgramIDare all allocated before any compilation checks. Earlyreturn nullptrpaths skipglDeleteShader/glDeleteProgram, leaking GPU handles. - Fix: Call
glDeleteShader(vertexShader); glDeleteShader(fragmentShader); glDeleteProgram(shaderProgramID);before each earlyreturn nullptr.
- File:
source/Game.h - Status:
[✅] - What:
eng::Mesh* m_mesh;has no initializer. IfInit()returns early before reachingm_mesh = new ..., the pointer holds garbage. - Fix: Change declaration to
eng::Mesh* m_mesh = nullptr;.
- File:
engine/source/render/Mesh.cpp - Status:
[✅] - What:
(void*)(uint32_t)layout.elements[i].offsetcasts through a 4-byte integer before converting to an 8-byte pointer. - Fix: Use
(void*)(uintptr_t)layout.elements[i].offset.
- File:
engine/source/render/RenderQueue.cpp - Status:
[✅] - What: When all 100 slots are used,
Submit()silently discards the command with no error. - Fix: Add
std::cerr << "ERROR: RenderQueue full, command dropped\n";(or an assert) when count reaches the limit.
- File:
engine/source/graphics/VertexLayout.h - Status:
[✅] - What: Uses
GLuintwithout including the header that defines it. Works by accident due to include order. - Fix: Add
#include <GL/glew.h>at the top ofVertexLayout.h.
| ID | Severity | File | Issue |
|---|---|---|---|
| BUG-01 | Critical | Material.cpp | Delete after assign — dangling pointer |
| BUG-02 | Critical | RenderQueue.cpp | delete[] on stack array — UB |
| BUG-03 | Critical | RenderQueue.cpp / Game.cpp | Storing address of local variable |
| BUG-04 | Critical | VertexLayout.h / Mesh.cpp | Rule of Three — shallow copy + dangling |
| BUG-05 | High | Mesh.h / Mesh.cpp | No destructor — GPU resource leak |
| BUG-06 | High | Material.cpp | Destructor commented out — leak |
| BUG-07 | High | Game.cpp | m_mesh never deleted in Destroy() |
| BUG-08 | High | GraphicsAPI.cpp | &vertices double-pointer — corrupt data |
| BUG-09 | Medium | GraphicsAPI.cpp | Shader handle leak on error path |
| BUG-10 | Medium | Game.h | m_mesh uninitialized pointer |
| BUG-11 | Low | Mesh.cpp | Offset cast truncation on 64-bit |
| BUG-12 | Low | RenderQueue.cpp | Silent drop when queue full |
| BUG-13 | Low | VertexLayout.h | Missing GLuint include |