-
Notifications
You must be signed in to change notification settings - Fork 100
Fix memory leak from repeated ProjDataInfo::clone() calls #1673
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?
Conversation
|
Based on CODACY suggestion I simplified a bit the set_template_proj_data_info() to use the shared_ptr |
KrisThielemans
left a comment
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.
I have flagged some minor style issues. In addition, it'd be best to add an overload for backwards compatibility.
void set_template_proj_data_info(const ProjDataInfo&);
which would then have to do the clone and call the other one, e.g.
set_template_proj_data_info(arg.make_shared_clone());
It's possible that you'd have to %ignore the new one in SWIG though.
| write_to_file("image_for", *image1_sptr); | ||
|
|
||
| image = *image.get_empty_copy(); | ||
| image.fill(0); //= *image.get_empty_copy(); |
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.
I'm happy with this, but let's remove the comment.
| image.fill(0); //= *image.get_empty_copy(); | |
| image.fill(0); |
| // rotate by 30 degrees | ||
| phi2 = 30 * _PI / 180; | ||
| VoxelsOnCartesianGrid<float> image2 = *image.get_empty_copy(); | ||
| VoxelsOnCartesianGrid<float> image2(image); // = *image.get_empty_copy(); |
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.
I see no good reason to do this, although I don't mind. (Should be equivalent, no?). If you prefer it this way, please delete the comment.
| write_to_file("image_to_fwp", *image1_sptr); | ||
|
|
||
| image = *image.get_empty_copy(); | ||
| image.fill(0); //= *image.get_empty_copy(); |
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.
delete comment
| write_to_file("image_with_voxel_at_30_0", *image1_sptr); | ||
|
|
||
| image = *image.get_empty_copy(); | ||
| image.fill(0); //= *image.get_empty_copy(); |
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.
delete comment
| if (dynamic_cast<const ProjDataInfoCylindricalNoArcCorr*>(proj_data_info_sptr.get())) | ||
| { | ||
| auto ptr = dynamic_cast<ProjDataInfoCylindricalNoArcCorr*>(proj_data_info_sptr.get()); | ||
| const auto* ptr = dynamic_cast<const ProjDataInfoCylindricalNoArcCorr*>(proj_data_info_sptr.get()); |
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.
I'm a bit confused that this works. const auto is a bit better than auto, but why make things more complicated by adding the *? It works without it (and means the same thing, I believe).
Same comment below of course.
|
|
||
| void | ||
| ScatterSimulation::set_template_proj_data_info(const ProjDataInfo& arg) | ||
| ScatterSimulation::set_template_proj_data_info(std::shared_ptr<const ProjDataInfo> arg) |
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.
| ScatterSimulation::set_template_proj_data_info(std::shared_ptr<const ProjDataInfo> arg) | |
| ScatterSimulation::set_template_proj_data_info(shared_ptr<const ProjDataInfo> arg) |
Of course, stir::shared_ptr is now std::shared_ptr, but we use this idiom everywhere...
| #endif | ||
| CartesianCoordinate3D<float> detector_coord_A, detector_coord_B; | ||
| auto ptr = dynamic_cast<ProjDataInfoBlocksOnCylindricalNoArcCorr*>(proj_data_info_sptr.get()); | ||
| const auto* ptr = dynamic_cast<const ProjDataInfoBlocksOnCylindricalNoArcCorr*>(proj_data_info_sptr.get()); |
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.
same comment on const auto*. I'd just use const auto
| void set_template_proj_data_info(const std::string&); | ||
|
|
||
| void set_template_proj_data_info(const ProjDataInfo&); | ||
| void set_template_proj_data_info(std::shared_ptr<const ProjDataInfo> arg); |
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.
| void set_template_proj_data_info(std::shared_ptr<const ProjDataInfo> arg); | |
| void set_template_proj_data_info(shared_ptr<const ProjDataInfo> arg); |
to be consistent with STIR styling
This PR fixes a memory leak detected by AddressSanitizer in ScatterSimulation::set_template_proj_data_info.
The issue was caused by calling arg.clone() multiple times inside dynamic_cast expressions, leading to leaked heap allocations when the cast failed.
The fix:
• Calls clone() exactly once
• Transfers ownership safely using a smart pointer
• Preserves the existing runtime type checks for supported ProjDataInfo types
This change is purely a memory-safety fix and does not alter behaviour or interfaces.
Changes in this pull request
Testing performed
Related issues
Checklist before requesting a review
documentation/release_XXX.mdhas been updated with any functionality change (if applicable)Contribution Notes
Please tick the following: