ordered json pointer corruption
mishase opened this issue · comments
Description
When using ordered json with push_back
call, pointer to previous structure gets corrupted
Reproduction steps
Use the code bellow with nlohmann::ordered_json
to get corrupted pointer
Expected vs. actual results
Expected output (same code, without ordered json):
string
string
{"a":{"b":"test"},"c":[1]}
Actual output (corrupted pointer):
string
number
{"a":{"b":"test"},"c":[1]}
Minimal code example
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::ordered_json; // use nlohmann::json to get correct result
int main()
{
auto obj = json::parse("{\"a\": {\"b\": \"test\"}}");
auto& ref = obj["a"]["b"];
std::cout << ref.type_name() << '\n'; // string
obj["c"] = json::array();
obj["c"].push_back(1);
std::cout << ref.type_name() << '\n'; // expected string, got number
std::cout << obj.dump(); // valid result, {"a":{"b":"test"},"c":[1]}
}
Error messages
No response
Compiler and operating system
Tested on ARM Windows and X64 Windows in Debug and Release modes
Library version
3.11.3
Validation
- The bug also occurs if the latest version from the
develop
branch is used. - I can successfully compile and run the unit tests.
This seems related to #4279.
As in the linked issue, you can't do that. The push_back function on vector can invalidate pointers, and ordered_json uses a vector.
It is related to the issue you mentioned earlier, but it's certainly NOT a documentation issue. ordered_json must have working push_back function without any pointer corruption or this function must be private if it can cause such behaviour. Please fix this
I have no idea how to fix it, so documentation is currently all we can do.
@mishase This behavior comes from std::vector<>::push_back()
, so not only is it not broken, it is standards conforming.
https://en.cppreference.com/w/cpp/container/vector/push_back
If after the operation the new size() is greater than old capacity() a reallocation takes place, in which case all iterators (including the end() iterator) and all references to the elements are invalidated. Otherwise only the end() iterator is invalidated.