Repository navigation
Fix exceptions from allocator-taking VLA move construction - #207
Merged
Merged
Conversation
This was referenced Sep 29, 2026
thirtytwobits
added this pull request to stack #210
September 29, 2026 21:11
thirtytwobits
force-pushed
the
codex/fix-vla-allocator-move-noexcept
branch
from
October 1, 2026 17:05
69da911 to
ff3de7f
Compare
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
POCMA-only allocators can still transfer storage between unequal allocators, causing deallocation through the wrong allocator.
Review effort: Balanced
Findings: 1
What changed in this PR
Updates allocator-aware VLA move construction so allocation failures can propagate.
Changes:
- Removes unconditional
noexceptfrom allocating moves. - Adds allocation-failure and allocator-trait regression tests.
- Preserves no-throw ordinary and storage-transfer moves.
| File | Description |
|---|---|
include/cetl/variable_length_array.hpp |
Adjusts move-constructor exception specifications. |
cetlvast/suites/unittest/test_variable_length_array_copy_and_move.cpp |
Tests allocator failure and source preservation. |
cetlvast/suites/unittest/test_variable_length_array_compiles.cpp |
Adds compile-time exception-specification checks. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
propagate_on_container_move_assignment applies to assignment and says nothing about whether the allocator passed to a constructor equals the source's. The base move constructor used it to select the overload that adopts the source's storage, so a POCMA allocator that is not always equal took the source's buffer even when the supplied allocator was a different instance. The destination later deallocated that buffer through the wrong allocator, and the public constructors were marked noexcept even though they must allocate in that case. - Select the storage-adopting base constructor only when is_always_equal. Otherwise use the runtime equality check, which allocates when unequal. - Base the public allocator-extended move constructors' noexcept on is_always_equal only, for both VariableLengthArray and the bool specialization. - Expect a POCMA allocator that is not always equal to be potentially throwing in the compile test. - Run the allocation-failure tests with both POCMA settings. With the previous dispatch the POCMA cases don't throw and deallocate through the wrong allocator. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pavel-kirienko
approved these changes
Oct 5, 2026
thirtytwobits
added a commit
that referenced
this pull request
Oct 5, 2026
Moving a VLA with an unequal allocator allocates only the source's occupied storage but records the source's full capacity. Spare capacity is therefore reported as usable memory even though it was never allocated, permitting out-of-bounds appends and incorrect deallocation counts. An empty source with reserved capacity can produce a destination with null storage and nonzero capacity. Record the allocated element count as the destination capacity in the unequal-allocator path. Equal-allocator moves continue transferring the original allocation and capacity. The shared fix covers both generic VLA elements and packed bool storage. Add six regression tests covering nonempty and empty sources with spare capacity, growth beyond the destination allocation, allocator ownership and deallocation counts, source reuse, and equal-allocator capacity transfer for both `int` and `bool`. Closes #205. Stacked on #207. This PR targets `codex/fix-vla-allocator-move-noexcept`, so its diff contains only the capacity fix and its tests. Merge #207 first, then retarget this PR to `main`. Validation: - Four regression cases fail before the fix; all six pass after it. - All eight VLA suites pass in C++14 under GCC 13.4 and Clang 22.1.8, in Debug and exceptions-disabled ReleaseEP configurations, with existing compiler/platform skips retained. - The new test suite passes C++17, C++20, and C++23 compilation under GCC and Clang, with exceptions enabled and disabled. - The six focused tests pass with Clang AddressSanitizer and UndefinedBehaviorSanitizer. - The original reproducer now reports `size=3 capacity=3 allocated=3`, with no deallocation-count mismatch. - Formatting and `git diff --check` pass. The head commit includes the documented `#verification` trigger so the verification workflow also runs while this PR targets another `codex/` branch. --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.


An allocator-taking VLA move can allocate new storage when the allocators differ. Its unconditional
noexceptcurrently turns an allocation failure intostd::terminate, preventing the caller from catchingstd::bad_alloc.Allow exceptions to propagate through the allocating base constructor and make both the generic and packed-bool public constructors' exception specifications match the existing allocator dispatch. Ordinary moves and the existing unconditional storage-transfer paths retain
noexcept.Add regression tests for allocation failure, preservation and subsequent reuse of the source, equal-allocator moves without allocation, and the exception specifications for all allocator-trait combinations. Capacity bookkeeping and partial-construction cleanup remain tracked separately in #205 and #37.
Closes #204.
Validation:
intandbool.std::bad_allocand exits successfully.git diff --checkpass.