Fix optional copy-assignment leak/self-assignment bug and set iterator types (#31)#34
Merged
Merged
Conversation
optional::operator=(optional const&) (the pre-C++17 fallback) set _value to nullptr without deleting the previous allocation, leaking it. For self- assignment it was worse: nulling _value first made has_value() return false, so the value was silently dropped. Add a self-assignment guard and reset() the old value before copying. set's begin()/end() declared their return types as std::set<TKey>::iterator (default comparator) while the member is std::set<TKey, TCompare>. These are the same type in practice but not guaranteed; spell them with TCompare. Added OptionalTest.SelfAssignmentTest, which fails on the old code (value dropped) and passes with the fix.
Owner
Author
|
@codex review |
|
Codex Review: Didn't find any major issues. Breezy! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the two robustness defects tracked in #31. Both are small, self-contained correctness/safety fixes with no behavior change for valid usage.
1.
optional::operator=— memory leak and self-assignment value lossinclude/optional.h(the pre-C++17 fallbackoptional; C++17 usesstd::optional)Two problems:
optionalthat already holds a value overwrites_valuewithoutdeleteing the previous heap allocation._value = nullptrruns first, so forv = vthe followingother.has_value()reads the just-nulled pointer, returnsfalse, and the value is silently dropped (and the original leaked).Fix — self-assignment guard, then
reset()(whichdeletes the old value) before copying:This mirrors the existing
operator=(T const&)overload, which already callsreset()first.2.
setiterator accessors — comparator-independent iterator typeinclude/set.hThe four
begin()/end()overloads declared their return types asstd::set<TKey>::iterator(default comparator), while the underlying member isstd::set<TKey, TCompare>. It compiles today only because astd::set's iterator type happens not to depend on its comparator in current implementations — that's not guaranteed by the standard. Spelled the return types correctly withTCompare.Tests
Added
OptionalTest.SelfAssignmentTest. I confirmed it fails on the old code (value dropped →value()aborts) and passes with the fix.Verification
Built and ran the full suite under Debug & Release × C++11 & C++17 — all green (302 tests in C++17, 286 in C++11). The C++11 configuration is what exercises the fallback
optional.Scope note
The original #31 report also listed
lazy_set::zip(vector)"dropping the comparator" and some cosmetic items. On inspection those are not bugs (the vector-zip overloads have noUCompareto preserve;std::lessis the correct dedup ordering, consistent withvector::distinct), so they were intentionally left out — see the updated issue for details.Closes #31.
https://claude.ai/code/session_011y3XcVg3UCcgi5JMEo2tso