-
Notifications
You must be signed in to change notification settings - Fork 0
Use callbacks on heap and introduce reference counting #20
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
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 | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -314,6 +314,8 @@ | |||||||||||||||||||||||||||||||||||||||
| funcCallback mfuncCallback[Events::NumEvents]; | ||||||||||||||||||||||||||||||||||||||||
| /// The data instance. | ||||||||||||||||||||||||||||||||||||||||
| void *mInstance{nullptr}; | ||||||||||||||||||||||||||||||||||||||||
| /// The reference count for the callback interface, used for memory management. | ||||||||||||||||||||||||||||||||||||||||
| uint32_t mNumRefs{ 0 }; | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+317
to
+318
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. Initialize With 🐛 Proposed fix /// The reference count for the callback interface, used for memory management.
- uint32_t mNumRefs{ 0 };
+ uint32_t mNumRefs{ 1 };🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /// @brief The default class constructor. | ||||||||||||||||||||||||||||||||||||||||
| CallbackI() : mfuncCallback{ nullptr } { | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -339,6 +341,21 @@ | |||||||||||||||||||||||||||||||||||||||
| mfuncCallback[i] = nullptr; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /// @brief Increment the reference count. | ||||||||||||||||||||||||||||||||||||||||
| void incRef() { | ||||||||||||||||||||||||||||||||||||||||
| ++mNumRefs; | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /// @brief Decrement the reference count. | ||||||||||||||||||||||||||||||||||||||||
| void decRef() { | ||||||||||||||||||||||||||||||||||||||||
| if (mNumRefs > 0) { | ||||||||||||||||||||||||||||||||||||||||
| --mNumRefs; | ||||||||||||||||||||||||||||||||||||||||
| if (mNumRefs == 0) { | ||||||||||||||||||||||||||||||||||||||||
| delete this; | ||||||||||||||||||||||||||||||||||||||||
|
Check failure on line 355 in src/tinyui.h
|
||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+351
to
+358
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.
Two concerns:
🛡️ Proposed safer implementation /// `@brief` Decrement the reference count.
- void decRef() {
- if (mNumRefs > 0) {
- --mNumRefs;
- if (mNumRefs == 0) {
- delete this;
- }
- }
+ /// `@return` true if the object was deleted, false otherwise.
+ bool decRef() {
+ assert(mNumRefs > 0 && "decRef called on object with zero refcount");
+ --mNumRefs;
+ if (mNumRefs == 0) {
+ delete this;
+ return true;
+ }
+ return false;
}Alternatively, for modern C++17, consider using 📝 Committable suggestion
Suggested change
🧰 Tools🪛 GitHub Check: SonarCloud Code Analysis[failure] 355-355: Rewrite the code so that you no longer need this "delete". 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /// @brief The event callback array. | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -271,6 +271,9 @@ ret_code Widgets::button(Id id, Id parentId, const char *text, const Rect &rect, | |||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| child->mCallback = callback; | ||||||||||||||||||||||||
| if (callback != nullptr) { | ||||||||||||||||||||||||
| callback->incRef(); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
Comment on lines
273
to
+276
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. Reference count leak when reassigning callback on existing widget.
🔧 Proposed fix: decrement old callback before assignment+ if (child->mCallback != nullptr) {
+ child->mCallback->decRef();
+ }
child->mCallback = callback;
if (callback != nullptr) {
callback->incRef();
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||
| if (text != nullptr) { | ||||||||||||||||||||||||
| child->mText.assign(text); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
@@ -294,6 +297,10 @@ ret_code Widgets::imageButton(Id id, Id parentId, const char *image, const Rect | |||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| child->mCallback = callback; | ||||||||||||||||||||||||
| if (callback != nullptr) { | ||||||||||||||||||||||||
| callback->incRef(); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
Comment on lines
299
to
+303
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. Same reference count leak issue as Apply the same fix here—call 🔧 Proposed fix+ if (child->mCallback != nullptr) {
+ child->mCallback->decRef();
+ }
child->mCallback = callback;
if (callback != nullptr) {
callback->incRef();
}🤖 Prompt for AI Agents |
||||||||||||||||||||||||
| if (image != nullptr) { | ||||||||||||||||||||||||
| child->mImage = loadIntoImageCache(ctx, image); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
@@ -395,6 +402,9 @@ ret_code Widgets::treeView(Id id, Id parentId, const char *title, const Rect &re | |||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| CallbackI *callback = new CallbackI(onTreeViewItemClicked, nullptr, Events::MouseButtonDownEvent); | ||||||||||||||||||||||||
| widget->mCallback = callback; | ||||||||||||||||||||||||
| if (callback != nullptr) { | ||||||||||||||||||||||||
| callback->incRef(); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| return ResultOk; | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: kimkulling/tiny_ui
Length of output: 172
🏁 Script executed:
Repository: kimkulling/tiny_ui
Length of output: 1971
🏁 Script executed:
Repository: kimkulling/tiny_ui
Length of output: 3404
🏁 Script executed:
Repository: kimkulling/tiny_ui
Length of output: 4818
🏁 Script executed:
Repository: kimkulling/tiny_ui
Length of output: 1941
Only the progressBar callback will leak; the button callback is properly managed.
The review comment incorrectly states that
incRef()is never called inWidgets::button(). Thebutton()function does callcallback->incRef()after assignment, sodynamicQuitCallbackwill be properly reference-counted and freed when the widget is destroyed.However,
Widgets::progressBar()does not callincRef(). It only assigns the callback and adds it toctx.mUpdateCallbackList. This meansdynamicUpdateProgressBarCallbackstarts withmNumRefs = 0, and when the widget is destroyed,decRef()will not delete it, causing a memory leak.🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis
[failure] 101-101: Replace the use of "new" with an operation that automatically manages the memory.
See more on https://sonarcloud.io/project/issues?id=kimkulling_tiny_ui&issues=AZzem9Sw5gyFWmdews0o&open=AZzem9Sw5gyFWmdews0o&pullRequest=20
[warning] 102-102: Replace the redundant type with "auto".
See more on https://sonarcloud.io/project/issues?id=kimkulling_tiny_ui&issues=AZzem9Sw5gyFWmdews0n&open=AZzem9Sw5gyFWmdews0n&pullRequest=20
[failure] 102-102: Replace the use of "new" with an operation that automatically manages the memory.
See more on https://sonarcloud.io/project/issues?id=kimkulling_tiny_ui&issues=AZzem9Sw5gyFWmdews0p&open=AZzem9Sw5gyFWmdews0p&pullRequest=20
[warning] 101-101: Replace the redundant type with "auto".
See more on https://sonarcloud.io/project/issues?id=kimkulling_tiny_ui&issues=AZzem9Sv5gyFWmdews0m&open=AZzem9Sv5gyFWmdews0m&pullRequest=20
🤖 Prompt for AI Agents