basic_json destructor allocates memory, violating noexcept semantics
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 50.6k
- Forks
- 7.5k
- Avg merge
- 4d 17h
- Merged PRs (30d)
- 58
Description
Description
The destructor of basic_json invokes json_value::destroy, which may allocate a large std::vector to flatten out its object/array hierarchy in order to avoid recursion. In the event of an allocation failure, the vector will throw an uncatchable std::bad_alloc, terminating the program.
(I noticed this while debugging a related issue, where destroying an invalidated JSON object caused a four-exabyte allocation.)
Reproduction steps
- Create a complex JSON document by nesting a few million arrays/objects in an arbitrary structure.
- Artificially exhaust the application's available memory.
- Destroy your JSON document.
Expected vs. actual results
Allocating a bunch of memory in a destructor is weird and widely understood to be unsafe.
Normal recursive destruction would be suitable for my use-case. If that is unacceptable, there are methods (such as forming an ad-hoc linked list) that could be used to avoid recursion without allocating. If those methods are unacceptable, a non-throwing allocator could be used with a fallback to recursive destruction in the event that no memory is available.
The latter approach is implemented by PR #4654.
Minimal code example
Error messages
Compiler and operating system
Win11/MSVC
Library version
3.12.0
Validation
- The bug also occurs if the latest version from the
developbranch is used. - I can successfully compile and run the unit tests.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading json_value::destroy and reviewing PR #4654, which the issue identifies as an implementation of one proposed approach. Check how destruction behaves when allocation fails, then compile and run the repository's unit tests. Done means basic_json destruction no longer performs a potentially throwing allocation or terminates on allocation failure.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100