# | User | Rating |
---|---|---|
1 | tourist | 3985 |
2 | jiangly | 3814 |
3 | jqdai0815 | 3682 |
4 | Benq | 3529 |
5 | orzdevinwang | 3526 |
6 | ksun48 | 3517 |
7 | Radewoosh | 3410 |
8 | hos.lyric | 3399 |
9 | ecnerwala | 3392 |
9 | Um_nik | 3392 |
# | User | Contrib. |
---|---|---|
1 | cry | 169 |
2 | maomao90 | 162 |
2 | Um_nik | 162 |
4 | atcoder_official | 161 |
5 | djm03178 | 158 |
6 | -is-this-fft- | 157 |
7 | adamant | 155 |
8 | awoo | 154 |
8 | Dominater069 | 154 |
10 | luogu_official | 150 |
Name |
---|
I can give you lessons in implementation to avoid these mistakes later, you can take my number from eyad
RIP
I don't get it, max(a, b) = max(b, a) right ?
The latter one involves a calculation, that changes the former.
RIP
No it's not, actually I still don't know why they are not the same
brutal
After 6 hours of debugging, the compiler was debugged.
Try it by writing a max function and see if it works.
Or try to change your compiler. You are using C++17 (GCC 7-32), use C++20 (GCC 13-64) might be that this will work.
Here's how to debug the code in 10 minutes
Step 1: Generate a random test case using
g++ gen.cpp && ./a.out > input.txt
Step 2: Compile with sanitizer and run against the test case
Step 3: Add bound checking for line 57
Step 4: Profit 269512762
Same behavior replicated here. Switching order fixes it. Interestingly, adding optimization level O0 or O2 both give random outputs.
My best guess for why this happens is that std::max evaluates the second half of the max function, at some point stores a reference to a value in the vector of nodes, but then reallocates the vector while resizing in the recursive step, messing with that reference.
This behavior could not be replicated on Godbolt (but I didn't try very hard). I'm also not familiar enough with low-level programming to use an actual debugger, so I can't give a better answer.
Is this a bug? It seems like a dangerous and easy to forget/not knowing how to fix it detail.
I suppose that this is a bug in the sense that it is not what you would expect happening. Also very frustrating if you don't know about it, get destroyed by it, and never understand why.
But think about it another way, assuming my understanding of the bug is correct. Let's say we want to implement a dynamically sized array. To make it dynamically sized, we will have to reallocate the memory for it every so often. If we want to allow usage of pointers to values inside this array, whenever we reallocate the array, we also have to redirect all the old pointers to the new array, which is a massive pain and may cause unwanted performance issues. Hence, this bug. (I actually discovered this the hard way during my country's TST last year...)
Combining a slightly aggressive compiler that uses references over values for performance along with the vector reference bug will likely generate this new bug.
One possible solution is to use BumpAllocator to manage allocations yourself
It seems to "fix" both of your codes: https://ideone.com/Q0kYAD and https://ideone.com/T8vPD4
Apply the trick on this blog's RTE code also results in AC: 269565959
Edit: It's not recommended to use the above method unless performance is the top priority, I'm simply proving a point that the behavior can be defined.
If you want references to survive a
push_back
, usedeque
instead ofvector
. In case you don't need references, compare with values instead. See https://ideone.com/xEPI3p and 269572580UB should be more suspected in this case, since the order of evaluation of parameters should not matter.
See the comment from qmk above.