-
Notifications
You must be signed in to change notification settings - Fork 14
Fix debug text rendering #323
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -396,6 +396,11 @@ | |||||||||||||||||||||||||||||
delete mKeyboardEvListener; | ||||||||||||||||||||||||||||||
mKeyboardEvListener = nullptr; | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
for (size_t i = 0; i < mScenes.size(); ++i) { | ||||||||||||||||||||||||||||||
// delete mScenes[i]; | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
mScenes.clear(); | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
Comment on lines
+399
to
+403
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainScene objects are leaked – heap-allocated
Minimal corrective patch: - for (size_t i = 0; i < mScenes.size(); ++i) {
- // delete mScenes[i];
- }
+ for (Scene *scene : mScenes) {
+ delete scene;
+ } Preferable long-term fix: change Please confirm that no other subsystem assumes ownership of these pointers before applying. 🏁 Script executed: #!/bin/bash
set -e
echo "=== mScenes Declaration in AppBase.cpp ==="
rg -n "mScenes" -n src/Engine/App/AppBase.cpp || true
echo "=== mScenes Declaration in AppBase.h ==="
rg -n "mScenes" -n src/Engine/App/AppBase.h || true
echo "=== Scene Allocations in onCreate methods ==="
rg -n "new Scene" -n src/Engine/App || true
echo "=== Any delete calls for mScenes elements ==="
rg -n "delete.*mScenes" -n src || true
rg -n "delete.*Scene" -n src/Engine/App/AppBase.cpp || true Length of output: 1227 Delete heap-allocated Scene objects in onDestroy to avoid memory leaks In src/Engine/App/AppBase.cpp (lines 399–403), the loop that should delete each - for (size_t i = 0; i < mScenes.size(); ++i) {
- // delete mScenes[i];
- }
- mScenes.clear();
+ for (Scene* scene : mScenes) {
+ delete scene;
+ }
+ mScenes.clear(); • Long-term, change 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||||||
osre_debug(Tag, "Set application state to destroyed."); | ||||||||||||||||||||||||||||||
mAppState = State::Destroyed; | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -29,25 +29,27 @@ | |||||||||||||||||||||||||||||||||||||
using namespace ::OSRE::RenderBackend; | ||||||||||||||||||||||||||||||||||||||
using namespace ::OSRE::Common; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
ServiceProvider *ServiceProvider::s_instance = nullptr; | ||||||||||||||||||||||||||||||||||||||
ServiceProvider *ServiceProvider::sInstance = nullptr; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
ServiceProvider *ServiceProvider::create() { | ||||||||||||||||||||||||||||||||||||||
if (nullptr == s_instance) { | ||||||||||||||||||||||||||||||||||||||
s_instance = new ServiceProvider; | ||||||||||||||||||||||||||||||||||||||
if (nullptr == sInstance) { | ||||||||||||||||||||||||||||||||||||||
sInstance = new ServiceProvider; | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
return s_instance; | ||||||||||||||||||||||||||||||||||||||
return sInstance; | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
void ServiceProvider::destroy() { | ||||||||||||||||||||||||||||||||||||||
if (nullptr != s_instance) { | ||||||||||||||||||||||||||||||||||||||
delete s_instance; | ||||||||||||||||||||||||||||||||||||||
s_instance = nullptr; | ||||||||||||||||||||||||||||||||||||||
if (nullptr != sInstance) { | ||||||||||||||||||||||||||||||||||||||
delete sInstance; | ||||||||||||||||||||||||||||||||||||||
sInstance = nullptr; | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
void ServiceProvider::setService(ServiceType type, Common::AbstractService *service) { | ||||||||||||||||||||||||||||||||||||||
s_instance->mServiceArray[static_cast<size_t>(type)] = service; | ||||||||||||||||||||||||||||||||||||||
if (type == ServiceType::Invalid || type == ServiceType::Count) { | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
Comment on lines
+50
to
+51
Check noticeCode scanning / CodeQL Futile conditional Note
If-statement with an empty then-branch and no else-branch.
Copilot AutofixAI 4 months ago To fix the issue, we need to address the empty then-branch of the
In this case, the best approach is to implement the then-branch to handle invalid service types explicitly. This ensures the code is robust and avoids potential misuse of the
Suggested changeset
1
src/Engine/App/ServiceProvider.cpp
Copilot is powered by AI and may make mistakes. Always verify output.
Positive FeedbackNegative Feedback
Refresh and try again.
Comment on lines
+50
to
+51
Check noticeCode scanning / CodeQL Empty branch of conditional Note
Empty block without comment.
Copilot AutofixAI 4 months ago To fix the issue, we need to address the empty block on line 51. The best approach depends on the intent of the code:
In this case, we will assume the first option (no action is required for the condition) and add a comment to clarify the intent. This ensures the code is more maintainable and avoids confusion for future developers.
Suggested changeset
1
src/Engine/App/ServiceProvider.cpp
Copilot is powered by AI and may make mistakes. Always verify output.
Positive FeedbackNegative Feedback
Refresh and try again.
|
||||||||||||||||||||||||||||||||||||||
sInstance->mServiceArray[static_cast<size_t>(type)] = service; | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
Comment on lines
+50
to
53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guard against The check for - if (type == ServiceType::Invalid || type == ServiceType::Count) {
- }
- sInstance->mServiceArray[static_cast<size_t>(type)] = service;
+ if (type == ServiceType::Invalid || type == ServiceType::Count) {
+ OSRE_ASSERT(false, "Attempt to register an invalid service type");
+ return;
+ }
+
+ OSRE_ASSERT(nullptr != sInstance, "ServiceProvider::create() was never called");
+ sInstance->mServiceArray[static_cast<size_t>(type)] = service; Fail-fast (assert / early-return) prevents undefined behaviour and makes misuse obvious in tests. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
ServiceProvider::ServiceProvider() : | ||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,18 +26,18 @@ namespace OSRE::Common { | |
|
||
using namespace ::cppcore; | ||
|
||
static const String EmptyToken = ""; | ||
|
||
size_t Tokenizer::getNumOfToken() const { | ||
return m_Token.size(); | ||
} | ||
|
||
const String &Tokenizer::getTokenAt( ui32 index ) const { | ||
if ( m_Token.isEmpty() || m_Token.size() >= index ) { | ||
return EmptyToken; | ||
bool Tokenizer::getTokenAt(size_t index, String &token) const { | ||
if ( m_Token.isEmpty() || m_Token.size() >= index ) { | ||
token = ""; | ||
return false; | ||
} | ||
|
||
return m_Token[ index ]; | ||
token = m_Token[index]; | ||
return true; | ||
} | ||
Comment on lines
+33
to
41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Off-by-one / reversed bound check causes the method to always report failure
- if ( m_Token.isEmpty() || m_Token.size() >= index ) {
- token = "";
- return false;
- }
+ if (m_Token.isEmpty() || index >= m_Token.size()) {
+ token = "";
+ return false;
+ } Without this fix every caller will assume the token was not found, breaking all parsing that relies on the tokenizer. 🤖 Prompt for AI Agents
|
||
|
||
bool Tokenizer::isEmpty() const { | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -29,18 +29,27 @@ | |||||||||||||||||||||||||||||
#include "RenderBackend/DbgRenderer.h" | ||||||||||||||||||||||||||||||
#include "RenderBackend/MaterialBuilder.h" | ||||||||||||||||||||||||||||||
#include "RenderBackend/MeshBuilder.h" | ||||||||||||||||||||||||||||||
#include "Properties/Settings.h" | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
namespace OSRE::RenderBackend { | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
using namespace ::OSRE::Common; | ||||||||||||||||||||||||||||||
using namespace ::OSRE::Properties; | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
DbgRenderer *DbgRenderer::sInstance = nullptr; | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
DbgRenderer::DbgRenderer(RenderBackendService *rbSrv) : | ||||||||||||||||||||||||||||||
mRbSrv(rbSrv), | ||||||||||||||||||||||||||||||
mDebugMesh(nullptr), | ||||||||||||||||||||||||||||||
mLastIndex(0) { | ||||||||||||||||||||||||||||||
osre_assert(nullptr != mRbSrv); | ||||||||||||||||||||||||||||||
auto *settings = rbSrv->getSettings(); | ||||||||||||||||||||||||||||||
i32 x = settings->getInt(Settings::WinX); | ||||||||||||||||||||||||||||||
i32 y = settings->getInt(Settings::WinY); | ||||||||||||||||||||||||||||||
i32 w = settings->getInt(Settings::WinWidth); | ||||||||||||||||||||||||||||||
i32 h = settings->getInt(Settings::WinHeight); | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
mCanvasRenderer = new CanvasRenderer(2, x, y, w, h); | ||||||||||||||||||||||||||||||
Check warningCode scanning / CodeQL Resource not released in destructor Warning
Resource mCanvasRenderer is acquired by class DbgRenderer but not released anywhere in this class.
Copilot AutofixAI 4 months ago To fix the issue, the Steps:
Suggested changeset
1
src/Engine/RenderBackend/DbgRenderer.cpp
Copilot is powered by AI and may make mistakes. Always verify output.
Positive FeedbackNegative Feedback
Refresh and try again.
|
||||||||||||||||||||||||||||||
mCanvasRenderer->create(); | ||||||||||||||||||||||||||||||
Comment on lines
+51
to
+52
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add null check after allocation and ensure proper cleanup. The CanvasRenderer allocation should be checked for success, and it needs to be properly deleted in the destructor to prevent memory leaks. Consider adding: mCanvasRenderer = new CanvasRenderer(2, x, y, w, h);
+if (mCanvasRenderer != nullptr) {
mCanvasRenderer->create();
+} Also, update the destructor: DbgRenderer::~DbgRenderer() {
clear();
+ delete mCanvasRenderer;
+ mCanvasRenderer = nullptr;
} 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
DbgRenderer::~DbgRenderer() { | ||||||||||||||||||||||||||||||
|
@@ -86,26 +95,16 @@ | |||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
DebugText *foundDebugText = getInstance()->getDebugText(id); | ||||||||||||||||||||||||||||||
mRbSrv->beginPass(RenderPass::getPassNameById(DbgPassId)); | ||||||||||||||||||||||||||||||
mRbSrv->beginRenderBatch(DbgRenderer::getDebugRenderBatchName()); | ||||||||||||||||||||||||||||||
glm::mat4 projection = glm::ortho(0.0f, 800.0f, 0.0f, 600.0f); | ||||||||||||||||||||||||||||||
mRbSrv->setMatrix(MatrixType::Projection, projection); | ||||||||||||||||||||||||||||||
if (foundDebugText == nullptr) { | ||||||||||||||||||||||||||||||
MeshBuilder meshBuilder; | ||||||||||||||||||||||||||||||
meshBuilder.allocTextBox(static_cast<f32>(x), static_cast<f32>(y), 20, text, BufferAccessType::ReadWrite); | ||||||||||||||||||||||||||||||
DebugText *entry = new DebugText; | ||||||||||||||||||||||||||||||
entry->mesh = meshBuilder.getMesh(); | ||||||||||||||||||||||||||||||
entry->mesh->setId(id); | ||||||||||||||||||||||||||||||
getInstance()->mDebugTextMeshes.add(entry); | ||||||||||||||||||||||||||||||
mRbSrv->setMatrix(MatrixType::Projection, projection); | ||||||||||||||||||||||||||||||
mRbSrv->addMesh(entry->mesh, 0); | ||||||||||||||||||||||||||||||
} else if (foundDebugText->text != text) { | ||||||||||||||||||||||||||||||
MeshBuilder::updateTextBox(foundDebugText->mesh, 10, text); | ||||||||||||||||||||||||||||||
mRbSrv->updateMesh(foundDebugText->mesh); | ||||||||||||||||||||||||||||||
DebugText *debugText = getInstance()->getDebugText(id); | ||||||||||||||||||||||||||||||
if (debugText == nullptr) { | ||||||||||||||||||||||||||||||
debugText = new DebugText; | ||||||||||||||||||||||||||||||
debugText->id = id; | ||||||||||||||||||||||||||||||
debugText->text = text; | ||||||||||||||||||||||||||||||
mDebugTextMeshes.add(debugText); | ||||||||||||||||||||||||||||||
} else if (debugText->text != text) { | ||||||||||||||||||||||||||||||
debugText->text = text; | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
mRbSrv->endRenderBatch(); | ||||||||||||||||||||||||||||||
mRbSrv->endPass(); | ||||||||||||||||||||||||||||||
mCanvasRenderer->drawText(x, y, 10, text); | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
static constexpr size_t NumIndices = 24; | ||||||||||||||||||||||||||||||
|
@@ -233,7 +232,7 @@ | |||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
DebugText *found = nullptr; | ||||||||||||||||||||||||||||||
for (size_t i = 0; i < mDebugTextMeshes.size(); ++i) { | ||||||||||||||||||||||||||||||
if (mDebugTextMeshes[i]->mesh->getId() == id) { | ||||||||||||||||||||||||||||||
if (mDebugTextMeshes[i]->id == id) { | ||||||||||||||||||||||||||||||
found = mDebugTextMeshes[i]; | ||||||||||||||||||||||||||||||
break; | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
|
@@ -242,4 +241,4 @@ | |||||||||||||||||||||||||||||
return found; | ||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
} // namespace OSRE::RenderBackend | ||||||||||||||||||||||||||||||
} // namespace OSRE::RenderBackend |
Check notice
Code scanning / CodeQL
Commented-out code Note
Copilot Autofix
AI 4 months ago
To fix the problem, we need to either remove the commented-out code or reinstate it if it is still relevant. In this case, the line
delete mScenes[i];
appears to be part of a cleanup process in theonDestroy
method, where other dynamically allocated resources are being deleted. If this line is necessary for proper cleanup, it should be reinstated. Otherwise, it should be removed entirely to avoid confusion.Given the context of the
onDestroy
method, it seems likely that the line was commented out by mistake or during debugging. Reinstating the line ensures that themScenes
objects are properly deleted, preventing potential memory leaks.