The problem is that a reader should not do anything with the data that is read, which depends on its value, before validating the copy, by counter comparison.
As another poster has said, the high-level languages leave undefined what happens when you copy non-atomically data that is written concurrently, but in fact the computer cannot catch fire when you do that, and the only thing that can happen is that the data may have values that are invalid for its type, e.g. an integer that is defined to belong in a range may have a value outside that range.
A much more serious problem that is not mentioned in TFA is that on computers that do not use Intel/AMD CPUs, this algorithm needs write barriers and read barriers. The writer must use 2 write barriers, after incrementing the counter before accessing the shared data, and before incrementing the counter after finishing with the shared data. Similarly the reader needs read barriers after the first reading of the counter and before the final reading of the counter.
From a hardware perspective this is correct. From a language perspective it's UB, and unless your compiler has defined that UB, it doesn't matter what the hardware's behavior is unless you're writing assembly.