-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix rule of three for SampleBuffer, SampleTCO #5727
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
Conversation
🤖 Hey, I'm @LmmsBot from github.com/lmms/bot and I made downloads for this pull request, click me to make them magically appear! 🎩
Linux
Windows
macOS🤖{"platform_name_to_artifacts": {"Linux": [{"artifact": {"title": {"title": "(AppImage)", "platform_name": "Linux"}, "link": {"link": "https://11836-15778896-gh.circle-artifacts.com/0/lmms-1.3.0-alpha.1.70%2Bgfe4e118-linux-x86_64.AppImage"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/11836?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}], "Windows": [{"artifact": {"title": {"title": "32-bit", "platform_name": "Windows"}, "link": {"link": "https://11835-15778896-gh.circle-artifacts.com/0/lmms-1.3.0-alpha.1.70%2Bgfe4e1188b-mingw-win32.exe"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/11835?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}, {"artifact": {"title": {"title": "64-bit", "platform_name": "Windows"}, "link": {"link": "https://11837-15778896-gh.circle-artifacts.com/0/lmms-1.3.0-alpha.1.70%2Bgfe4e1188b-mingw-win64.exe"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/11837?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}], "macOS": [{"artifact": {"title": {"title": "", "platform_name": "macOS"}, "link": {"link": "https://11839-15778896-gh.circle-artifacts.com/0/lmms-1.3.0-alpha.1.70%2Bgfe4e1188b-mac10.14.dmg"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/11839?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}]}, "commit_sha": "8789faf5632fab25b71199ed7c8fa954cb8918fd"} |
|
The rule of three (or five these days, now we have move constructors and assignment operators) doesn't say that objects have to be copyable or moveable; rather it says that if any of these functions are user-defined, the others should be user-defined too, because the compiler-generated ones are likely to be incorrect. If you write a destructor, you are probably trying to dispose of a resource when the object is destructed. The compiler-generated constructors and assignment operators will copy the resource handle, meaning it will be disposed of twice, and the compiler-generated assignment operators will overwrite the existing handle without disposing of it. If a particular constructor or assigment operator doesn't make sense, or you're not sure what to do at the moment,
|
|
Will fix merge conflicts as soon as I know that there aren't bigger issues remaining! |
Co-authored-by: Dominic Clark <[email protected]>
... by switching from an initializer list to manual assignments.
src/core/SampleBuffer.cpp
Outdated
| memcpy(m_origData, orig.m_origData, m_origFrames * BYTES_PER_FRAME); | ||
| memcpy(m_data, orig.m_data, m_frames * BYTES_PER_FRAME); |
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.
orig.m_origData or orig.m_data can be null, such as for a default-constructed SampleBuffer. Calling memcpy with a null pointer is undefined behaviour, even if the size is zero.
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.
In addition to the comment above, MOST implementations of memcpy does nothing if the length is 0, but it's not guaranteed that ALL implementations do nothing.
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.
Hopefully fixed in latest commit
| SampleTCO::SampleTCO(const SampleTCO& orig) : | ||
| SampleTCO(orig.getTrack()) | ||
| { | ||
| // TODO: This creates a new SampleBuffer for the new TCO, eating up memory | ||
| // & eventually causing performance issues. Letting tracks share buffers | ||
| // when they're identical would fix this, but isn't possible right now. | ||
| m_sampleBuffer = new SampleBuffer(*orig.m_sampleBuffer); | ||
| m_isPlaying = orig.m_isPlaying; | ||
| } |
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.
The constructor delegated to here initialises m_sampleBuffer with a newly allocated, default-constructed SampleBuffer. It is then leaked when this constructor overwrites it.
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.
Hopefully fixed in latest commit
|
I personally think it's more easily understandable to use the I'll approve it, just want to review it with more time later. |
Wow, I totally forgot about that. As you say though, it doesn't seem necessary.
Copying the std::swap() method would require:
With our bracket standards this would be a lot of lines.
👍 |
IanCaio
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.
LGTM! 🚀
|
Any objections to merging this? |
I'm going to ignore style review this time and say no objections. 👍 |
DomClark
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.
LGTM now. I made one comment, but it can be ignored if you want.
Co-authored-by: Dominic Clark <[email protected]>
|
Master CI fails in the same way as this, so I'll merge now 🎉 |
* Automatic formatting changes * Add copy constructor and assignemnt to SampleBuffer * Add copy constructor to SampleTCO * Delete SampleTCO copy assignment, initial work on SampleBuffer swap method * SampleBuffer: Finish(?) swap and use it for copy assignment, lock for read in copy constructor * Don't forget to unlock in copy assignment! * Formatting changes * Lock ordering in swap * Fix leak and constness Co-authored-by: Dominic Clark <[email protected]> * Fix multiplication style, ensure lock is held when necessary ... by switching from an initializer list to manual assignments. * Fixes from review * Avoid more undefined behavior * Update src/tracks/SampleTrack.cpp Co-authored-by: Dominic Clark <[email protected]>
* Automatic formatting changes * Add copy constructor and assignemnt to SampleBuffer * Add copy constructor to SampleTCO * Delete SampleTCO copy assignment, initial work on SampleBuffer swap method * SampleBuffer: Finish(?) swap and use it for copy assignment, lock for read in copy constructor * Don't forget to unlock in copy assignment! * Formatting changes * Lock ordering in swap * Fix leak and constness Co-authored-by: Dominic Clark <[email protected]> * Fix multiplication style, ensure lock is held when necessary ... by switching from an initializer list to manual assignments. * Fixes from review * Avoid more undefined behavior * Update src/tracks/SampleTrack.cpp Co-authored-by: Dominic Clark <[email protected]>
* Automatic formatting changes * Add copy constructor and assignemnt to SampleBuffer * Add copy constructor to SampleTCO * Delete SampleTCO copy assignment, initial work on SampleBuffer swap method * SampleBuffer: Finish(?) swap and use it for copy assignment, lock for read in copy constructor * Don't forget to unlock in copy assignment! * Formatting changes * Lock ordering in swap * Fix leak and constness Co-authored-by: Dominic Clark <[email protected]> * Fix multiplication style, ensure lock is held when necessary ... by switching from an initializer list to manual assignments. * Fixes from review * Avoid more undefined behavior * Update src/tracks/SampleTrack.cpp Co-authored-by: Dominic Clark <[email protected]>
Custom destruction, copy constructors, and copy assignment should usually all be implemented for a class that implements any one of them. These changes are needed for #5524, but I decided to move them to a separate PR to split the review burden, especially since it's important (and tricky, IMO) to get these correct.
Status as of latest commit