Memory load reordering optimization (-O2) bug
Same GCC version does not have this bug
Reply To nik-ponomarev
Same GCC version does not have this bug
With respect, that's an asinine, and utterly meaningless statement; you are reporting an issue with a specific version of GCC so obviously that particular version of GCC does exhibit the issue.
I'm sorry to say this, but while we thank you for the heads-up, (which will enable us to check whether, or not, our distribution of GCC-7.3 exhibits this issue), we simply cannot help you to resolve your issue, because your report clearly demonstrates that you are not using our GCC distribution; you must seek assistance from the distributor of the compiler you are actually using, (which is not ours), or escalate it upstream to gcc.org. Furthermore, just because some GCC-7.3 build, presumably for some other platform, doesn't exhibit the issue, that does not preclude a bug in target specific gcc.org code, in which case reporting your issue upstream would be entirely appropriate.
Ok, many thanks for the detailed and informative instructions! I will submit the issue to GCC bug-tracker.
I don't know exactly what you are trying to demonstrate, with your test case, but if I understand you correctly, you tripped over some unexpected behaviour with std::atomic. FWIW, if I substitute std::atomic<int32_t>, (having also added #include <cstdint>), for your home-brewed alternative struct atomic:
Then cross-compile and run it (under wine), with the Linux hosted build of our GCC-7.3.0:
- #include <cstdint>
- #include <iostream>
- #include <cstring>
- #include <atomic>
- struct TestStruct
- { std::atomic<int32_t> storage;
- TestStruct(){ memset(static_cast<void *>(&storage),-1,sizeof(storage)); }
- void operator()(unsigned long i)
- { std::atomic<int32_t>* ptr2 = new (&storage) std::atomic<int32_t>(i);
- unsigned long val1 = ptr2->load();
- std::cout << "Expected: " << i << "; First load value: " << val1 << std::endl;
- unsigned long val2 = ptr2->load();
- std::cout << "Expected: " << i << "; Second load value: " << val2 << std::endl;
- }
- };
- int main()
- { TestStruct()(0UL);
- return 0;
- }
$ mingw32-g++ -O2 --std=gnu++11 t_atomic.cpp $ ./a.exe Expected: 0; First load value: 0 Expected: 0; Second load value: 0Isn't this the behaviour you expect?
BTW, I'm no expert in C++, (in fact, I find that it all too frequently degenerates into inscrutable black magic), doesn't that new operator in my line 11, (corresponding to your line 26), create a memory leak?
Reply To keith
BTW, I'm no expert in C++, (in fact, I find that it all too frequently degenerates into inscrutable black magic), doesn't that new operator in my line 11, (corresponding to your line 26), create a memory leak?
I guess it doesn't. As I said, I'm no expert in C++, and I'd never seen the "placement" overload of new before. Some research tells me that this usage is simply creating a new pointer, referring to an existing memory "allocation"; there is no newly allocated memory to leak.
Description
The bug is related to some internal code structure, so tried to reproduce the situation as close as possible. mingw with -O2 optimization flag loads memset-ed value on the first load of atomic (just struct name) value read and initialized value (right value) at the second load call.
Fixes:
* Removing volatile keyword
* Changing int32_t to unsigned long
* Other reduction of code complexity
What is wrong with this code? Is it a bug? GCC7 does not have this issue.
Reproducer
Output:
Environment