Can we use std::atomic<std::array<>>? [duplicate] - c++

In 29.5 Atomic types of the C++ Standard November 2014 working draft it states:
There is a generic class template atomic. The type of the template argument T shall be trivially copyable (3.9). [ Note: Type arguments that are not also statically initializable may be difficult to use. —end note ]
So - as far as I can tell - this:
#include <atomic>
struct Message {
unsigned long int a;
unsigned long int b;
};
std::atomic<Message> sharedState;
int main() {
Message tmp{1,2};
sharedState.store(tmp);
Message tmp2=sharedState.load();
}
should be perfectly valid standard c++14 (and also c++11) code. However, if I don't link libatomic manually, the command
g++ -std=c++14 <filename>
gives - at least on Fedora 22 (gcc 5.1) - the following linking error:
/tmp/ccdiWWQi.o: In function `std::atomic<Message>::store(Message, std::memory_order)':
main.cpp:(.text._ZNSt6atomicI7MessageE5storeES0_St12memory_order[_ZNSt6atomicI7MessageE5storeES0_St12memory_order]+0x3f): undefined reference to `__atomic_store_16'
/tmp/ccdiWWQi.o: In function `std::atomic<Message>::load(std::memory_order) const':
main.cpp:(.text._ZNKSt6atomicI7MessageE4loadESt12memory_order[_ZNKSt6atomicI7MessageE4loadESt12memory_order]+0x1c): undefined reference to `__atomic_load_16'
collect2: error: ld returned 1 exit status
If I write
g++ -std=c++14 -latomic <filename>
everything is fine.
I know that the standard doesn't say anything about compiler flags or libraries that have to be included, but so far I thought that any standard conformant, single file code can be compiled via the first command.
So why doesn't that apply to my example code? Is there a rational why -latomic is still necessary, or is it just something that hasn't been addressed by the compiler maintainers, yet?

Relevant reading on the GCC homepage on how and why GCC makes library calls in certain cases regarding <atomic> in the first place.
GCC and libstdc++ are only losely coupled. libatomic is the domain of the library, not the compiler -- and you can use GCC with a different library (which might provide the necessary definitions for <atomic> in its main proper, or under a different name), so GCC cannot just assume -latomic.
Also:
GCC 4.7 does not include a library implementation as the API has not been firmly established.
The same page claims that GCC 4.8 shall provide such a library implementation, but plans are the first victims of war. I'd guess the reason for -latomic still being necessary can be found in that vicinity.
Besides...
...so far I thought that any standard conformant, single file code can be compiled via the first command.
...-lm has been around for quite some time if you're using math functions.

I know that the standard doesn't say anything about compiler flags or libraries that have to be included
Right.
but so far I thought that any standard conformant, single file code can be compiled via the first command.
Well, no. As you just said, there is no particular reason to assume this. Consider also that GCC extensions are enabled by default.
That being said, it seems self-evident that the intention is to make -latomic a default part of the runtime when it's settled down a bit.

g++ is a wrapper for gcc which adds the correct C++ libraries. Clearly -latomic is missing from that list. Not a core compiler problem then, simply a minor bug in the wrapper.

Related

Is it allowed to name a global variable `read` or `malloc` in C++?

Consider the following C++17 code:
#include <iostream>
int read;
int main(){
std::ios_base::sync_with_stdio(false);
std::cin >> read;
}
It compiles and runs fine on Godbolt with GCC 11.2 and Clang 12.0.1, but results in runtime error if compiled with a -static key.
As far as I understand, there is a POSIX(?) function called read (see man read(2)), so the example above actually invokes ODR violation and the program is essentially ill-formed even when compiled without -static. GCC even emits warning if I try to name a variable malloc: built-in function 'malloc' declared as non-function
Is the program above valid C++17? If no, why? If yes, is it a compiler bug which prevents it from running?
The code shown is valid (all C++ Standard versions, I believe). The similar restrictions are all listed in [reserved.names]. Since read is not declared in the C++ standard library, nor in the C standard library, nor in older versions of the standard libraries, and is not otherwise listed there, it's fair game as a name in the global namespace.
So is it an implementation defect that it won't link with -static? (Not a "compiler bug" - the compiler piece of the toolchain is fine, and there's nothing forbidding a warning on valid code.) It does at least work with default settings (though because of how the GNU linker doesn't mind duplicated symbols in an unused object of a dynamic library), and one could argue that's all that's needed for Standard compliance.
We also have at [intro.compliance]/8
A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any well-formed program. Implementations are required to diagnose programs that use such extensions that are ill-formed according to this International Standard. Having done so, however, they can compile and execute such programs.
We can consider POSIX functions such an extension. This is intentionally vague on when or how such extensions are enabled. The g++ driver of the GCC toolset links a number of libraries by default, and we can consider that as adding not only the availability of non-standard #include headers but also adding additional translation units to the program. In theory, different arguments to the g++ driver might make it work without the underlying link step using libc.so. But good luck - one could argue it's a problem that there's no simple way to link only names from the C++ and C standard libraries without including other unreserved names.
(Does not altering a well-formed program even mean that an implementation extension can't use non-reserved names for the additional libraries? I hope not, but I could see a strict reading implying that.)
So I haven't claimed a definitive answer to the question, but the practical situation is unlikely to change, and a Standard Defect Report would in my opinion be more nit-picking than a useful clarification.
Here is some explanation on why it produces a runtime error with -static only.
The https://godbolt.org/z/asKsv95G5 link in the question indicates that the runtime error with -static is Program returned: 139. The output of kill -l in Bash on Linux contains 11) SIGSEGV (and 128 + 11 = 139), so the process exits with fatal signal SIGSEGV (Segmentation fault) indicating invalid memory reference. The reason for that is that the process tries to run the contents (4 bytes) of the read variable as machine code. (Eventually std::cin >> ... calls read.) Either somethings fails in those 4 bytes accidentally interpreted as machine code, or it fails because the memory page containing those 4 bytes is not executable.
The reason why it succeeds without -static is that with dynamic linking it's possible to have multiple symbols with the same name (read): one in the program executable, and another one in the shared library (libc.so.6). std::cin >> ... (in libstdc++.so.6) links against libc.so.6, so when the dynamic linker tries to find the symbol read at program load time (to be used by libstdc++.so.6), it will look at libc.so.6 first, finding read there, and ignoring the read symbol in the program executable.

In C++11 the signal.h header has no kill function

I just tried compiling code that I wrote a while ago using Gnu g++ in C++11 mode, to see if the code will need reworking anytime soon (I also plan to test it in C++17 mode for the same reason).
I found that the kill() function caused a compiler error and it seems that the kill function no longer exists in the signal.h header.
I just looked at http://www.cplusplus.com/reference/csignal/ as a reference which seems to confirm this is not just a Gnu-specific omission, but seems to be in the standard.
I can't find a rationale for this omission anywhere, nor can I find any proposal for how I should manage processes without it. Can anyone point me in the right direction?
C++ standard function is raise.
kill is a POSIX function that requires POSIX process id pid_t, none of which is required in C++ standard.
OK, I was too quick to post that question, of course fork/kill etc are not part of the C++ standard in the first place but are common additions on unix-like platforms.
My real problem was that I used the wrong compiler switch. For anyone else hitting this problem, to get strict C++11 standard, use:
g++ -std=c++11
But to get the C++11 standard plus non-standard extensions use:
g++ -std=gnu++11
Using the latter, I can build and call fork/kill no problem.

std::atomic<struct sigaction> is not supported? [duplicate]

In 29.5 Atomic types of the C++ Standard November 2014 working draft it states:
There is a generic class template atomic. The type of the template argument T shall be trivially copyable (3.9). [ Note: Type arguments that are not also statically initializable may be difficult to use. —end note ]
So - as far as I can tell - this:
#include <atomic>
struct Message {
unsigned long int a;
unsigned long int b;
};
std::atomic<Message> sharedState;
int main() {
Message tmp{1,2};
sharedState.store(tmp);
Message tmp2=sharedState.load();
}
should be perfectly valid standard c++14 (and also c++11) code. However, if I don't link libatomic manually, the command
g++ -std=c++14 <filename>
gives - at least on Fedora 22 (gcc 5.1) - the following linking error:
/tmp/ccdiWWQi.o: In function `std::atomic<Message>::store(Message, std::memory_order)':
main.cpp:(.text._ZNSt6atomicI7MessageE5storeES0_St12memory_order[_ZNSt6atomicI7MessageE5storeES0_St12memory_order]+0x3f): undefined reference to `__atomic_store_16'
/tmp/ccdiWWQi.o: In function `std::atomic<Message>::load(std::memory_order) const':
main.cpp:(.text._ZNKSt6atomicI7MessageE4loadESt12memory_order[_ZNKSt6atomicI7MessageE4loadESt12memory_order]+0x1c): undefined reference to `__atomic_load_16'
collect2: error: ld returned 1 exit status
If I write
g++ -std=c++14 -latomic <filename>
everything is fine.
I know that the standard doesn't say anything about compiler flags or libraries that have to be included, but so far I thought that any standard conformant, single file code can be compiled via the first command.
So why doesn't that apply to my example code? Is there a rational why -latomic is still necessary, or is it just something that hasn't been addressed by the compiler maintainers, yet?
Relevant reading on the GCC homepage on how and why GCC makes library calls in certain cases regarding <atomic> in the first place.
GCC and libstdc++ are only losely coupled. libatomic is the domain of the library, not the compiler -- and you can use GCC with a different library (which might provide the necessary definitions for <atomic> in its main proper, or under a different name), so GCC cannot just assume -latomic.
Also:
GCC 4.7 does not include a library implementation as the API has not been firmly established.
The same page claims that GCC 4.8 shall provide such a library implementation, but plans are the first victims of war. I'd guess the reason for -latomic still being necessary can be found in that vicinity.
Besides...
...so far I thought that any standard conformant, single file code can be compiled via the first command.
...-lm has been around for quite some time if you're using math functions.
I know that the standard doesn't say anything about compiler flags or libraries that have to be included
Right.
but so far I thought that any standard conformant, single file code can be compiled via the first command.
Well, no. As you just said, there is no particular reason to assume this. Consider also that GCC extensions are enabled by default.
That being said, it seems self-evident that the intention is to make -latomic a default part of the runtime when it's settled down a bit.
g++ is a wrapper for gcc which adds the correct C++ libraries. Clearly -latomic is missing from that list. Not a core compiler problem then, simply a minor bug in the wrapper.

Why does g++ still require -latomic

In 29.5 Atomic types of the C++ Standard November 2014 working draft it states:
There is a generic class template atomic. The type of the template argument T shall be trivially copyable (3.9). [ Note: Type arguments that are not also statically initializable may be difficult to use. —end note ]
So - as far as I can tell - this:
#include <atomic>
struct Message {
unsigned long int a;
unsigned long int b;
};
std::atomic<Message> sharedState;
int main() {
Message tmp{1,2};
sharedState.store(tmp);
Message tmp2=sharedState.load();
}
should be perfectly valid standard c++14 (and also c++11) code. However, if I don't link libatomic manually, the command
g++ -std=c++14 <filename>
gives - at least on Fedora 22 (gcc 5.1) - the following linking error:
/tmp/ccdiWWQi.o: In function `std::atomic<Message>::store(Message, std::memory_order)':
main.cpp:(.text._ZNSt6atomicI7MessageE5storeES0_St12memory_order[_ZNSt6atomicI7MessageE5storeES0_St12memory_order]+0x3f): undefined reference to `__atomic_store_16'
/tmp/ccdiWWQi.o: In function `std::atomic<Message>::load(std::memory_order) const':
main.cpp:(.text._ZNKSt6atomicI7MessageE4loadESt12memory_order[_ZNKSt6atomicI7MessageE4loadESt12memory_order]+0x1c): undefined reference to `__atomic_load_16'
collect2: error: ld returned 1 exit status
If I write
g++ -std=c++14 -latomic <filename>
everything is fine.
I know that the standard doesn't say anything about compiler flags or libraries that have to be included, but so far I thought that any standard conformant, single file code can be compiled via the first command.
So why doesn't that apply to my example code? Is there a rational why -latomic is still necessary, or is it just something that hasn't been addressed by the compiler maintainers, yet?
Relevant reading on the GCC homepage on how and why GCC makes library calls in certain cases regarding <atomic> in the first place.
GCC and libstdc++ are only losely coupled. libatomic is the domain of the library, not the compiler -- and you can use GCC with a different library (which might provide the necessary definitions for <atomic> in its main proper, or under a different name), so GCC cannot just assume -latomic.
Also:
GCC 4.7 does not include a library implementation as the API has not been firmly established.
The same page claims that GCC 4.8 shall provide such a library implementation, but plans are the first victims of war. I'd guess the reason for -latomic still being necessary can be found in that vicinity.
Besides...
...so far I thought that any standard conformant, single file code can be compiled via the first command.
...-lm has been around for quite some time if you're using math functions.
I know that the standard doesn't say anything about compiler flags or libraries that have to be included
Right.
but so far I thought that any standard conformant, single file code can be compiled via the first command.
Well, no. As you just said, there is no particular reason to assume this. Consider also that GCC extensions are enabled by default.
That being said, it seems self-evident that the intention is to make -latomic a default part of the runtime when it's settled down a bit.
g++ is a wrapper for gcc which adds the correct C++ libraries. Clearly -latomic is missing from that list. Not a core compiler problem then, simply a minor bug in the wrapper.

-O1/2/3 with -std=c++1y/11/98 - If <cmath> is included i'm getting error: '_hypot' was not declared in this scope

I've just updated MinGW using mingw-get-setup and i'm unable to build anyting that contains <cmath> header if I use anything larger than -O0 with -std=c++1y. (I also tried c++11 and c++98) I'm getting errors like this one:
g++.exe -pedantic-errors -pedantic -Wextra -Wall -std=c++1y -O3 -c Z:\Projects\C++\L6\src\events.cpp -o obj\src\events.o
In file included from z:\lander\mingw\lib\gcc\mingw32\4.8.1\include\c++\cmath:44:0,
from Z:\Projects\C++\L6\src\utils.h:4,
from Z:\Projects\C++\L6\src\events.cpp:10:
z:\lander\mingw\include\math.h: In function 'float hypotf(float, float)':
z:\lander\mingw\include\math.h:635:30: error: '_hypot' was not declared in this scope
{ return (float)(_hypot (x, y)); }
Is something wrong on my side?
Or version at mingw repo is bugged? And if so, is there any quick fix for this header?
To avoid any further speculation, and downright bad suggestions such as using #if 0, let me give an authoritative answer, from the perspective of a MinGW project contributor.
Yes, the MinGW.org implementation of include/math.h does have a bug in its inline implementation of hypotf (float, float); the bug is triggered when compiling C++, with the affected header included (as it is when cmath is included), and any compiler option which causes __STRICT_ANSI__ to become defined is specified, (as is the case for those -std=c... options noted by the OP). The appropriate solution is not to occlude part of the math.h file, with #if 0 or otherwise, but to correct the broken inline implementation of hypotf (float, float); simply removing the spurious leading underscore from the inline reference to _hypot (float, float), where its return value is cast to the float return type should suffice.
Alternatively, substituting an equivalent -std=gnu... for -std=c... in the compiler options should circumvent the bug, and may offer a suitable workaround.
FWIW, I'm not entirely happy with MinGW.org's current implementation of hypotl (long double, long double) either; correcting both issues is on my punch list for the next release of the MinGW runtime, but ATM, I have little time to devote to preparing this.
Update
This bug is no longer present in the current release of the MinGW.org runtime library (currently mingwrt-3.22.4, but fixed since release 3.22). If you are using anything older than this, (including any of the critically broken 4.x releases), you should upgrade.
As noted by Keith, this is a bug in the MinGW.org header.
As an alternative to editing the MinGW.org header, you can use MinGW-w64, which provides everything MinGW.org provides, and a whole lot more.
For a list of differences between the runtimes, see this wiki page.
MinGW uses gcc and the Microsoft runtime library. Microsoft's implementation support C90, but its support for later versions of the C standard (C99 and C11) is very poor.
The hypot function (along with hypotf and hypotl) was added in C99.
If you're getting this error with a program that calls hypot, such as:
#include <cmath>
int main() {
std::cout << std::hypot(3.0, 4.0)) << '\n';
}
then it's just a limitation of the Microsoft runtime library, and therefore of MinGW. If it occurs with any program that has #include <cmath>, then it's a bug, perhaps a configuration error, in MinGW.