Large global array of vectors causing compilation error - c++

I have a very simple C++ code (it was a large one, but I stripped it to the essentials), but it's failing to compile. I'm providing all the details below.
The code
#include <vector>
const int SIZE = 43691;
std::vector<int> v[SIZE];
int main() {
return 0;
}
Compilation command: g++ -std=c++17 code.cpp -o code
Compilation error:
/var/folders/l5/mcv9tnkx66l65t30ypt260r00000gn/T//ccAtIuZq.s:449:29: error: unexpected token in '.section' directive
.section .data.rel.ro.local
^
GCC version: gcc version 12.1.0 (Homebrew GCC 12.1.0_1)
Operating system: MacOS Monterey, version 12.3, 64bit architecture (M1)
My findings and remarks:
The constant SIZE isn't random here. I tried many different values, and SIZE = 43691 is the first one that causes the compilation error.
My guess is that it is caused by stack overflow. So I tried to compile using the flag -Wl,-stack_size,0x20000000, and also tried ulimit -s 65520. But neither of them has any effect on the issue, the code still fails to compile once SIZE exceeds 43690.
I also calculated the amount of stack memory this code consumes when SIZE = 43690. AFAIK, vectors use 24B stack memory, so the total comes to 24B * 43690 = 1048560B. This number is very close to 220 = 1048576. In fact, SIZE = 43691 is the first time that the consumed stack memory exceeds 220B. Unless this is quite some coincidence, my stack memory is somehow limited to 220B = 2M. If that really is the case, I still cannot find any way to increase it via the compilation command arguments. All the solutions in the internet leads to the stack_size linker argument, but it doesn't seem to work on my machine. I'm wondering now if it's because of the M1 chip somehow.
I'm aware that I can change this code to use vector of vectors to consume memory from the heap, but I have to deal with other's codes very often who are used to coding like this.
Let me know if I need to provide any more details. I've been stuck with this the whole day. Any help would be extremely appreciated. Thanks in advance!

I had the same issue, and after adding the -O2 flag to the compilation command, it started working. No idea why.
So, something like this:
g++-12 -O2 -std=c++17 code.cpp -o code

It does seem to be an M1 / M1 Pro issue. I tested your code on two seperate M1 Pro machine with the same result as yours. One workaround I found is to use the x86_64 version of gcc under rosetta, which doesn't have these allocation problems.

Works on a M1 Max running Monterey 12.5.1 with XCode 13.4.1 and using clang 13.1.6 compiler:
% cat code.cpp
#include <vector>
const int SIZE = 43691;
std::vector<int> v[SIZE];
int main() {
return 0;
}
% cc -std=c++17 code.cpp -o code -lc++
% ./code
Also fails with gcc-12.2.0:
% g++-12 -std=c++17 code.cpp -o code
/var/tmp/ccEnyMCk.s:449:29: error: unexpected token in '.section' directive
.section .data.rel.ro.local
^
So it seems to be a gcc issue on M1 issue.

This is a gcc-12 problem on Darwin Aarch64 targets. It shall not emit such sections like .section .data.rel.ro.local. Section names on macOS shall start with __, eg.: .section __DATA,...
See Mach-O reference.

Related

Clang ast-dump results in infinite loop

For some reason when I try to get the ast-dump of any C/C++ code with Clang, I get an infinite loop which eventually results in clang: error: linker command failed with exit code 1136 or some similar error code.
I'm running Windows 10 with Clang version 13.0 (Also tried Clang 12.0 with same issues). I run the command clang -Xclang -ast-dump filename.c.
I've tried multiple files, but at this point I'm just trying to get a hello world ast (which compiles and runs fine via clang).
#include <stdio.h>
int main()
{
printf("Hello, World!\n");
return 0;
}
I'm sure I'm missing something simple, but I'd appreciate any help, thanks!
It's not an infinite loop if it terminates. :-)
The dumped AST includes stdio.h, which you included, so it's quite big (about 800 lines, when I tried it).
The error message is because the clang compiler (cc1) does not produce an object file when you pass it the -ast-dump option, but the clang driver (clang) doesn't know that. The driver is expecting to be able to link the generated object file into an executable, but it doesn't find the object file so it complains.
Use
clang -Xclang -ast-dump -fsyntax-only filename.c
to terminate the driver after the AST has been dumped.

C++ Increase Atomic Float

I have a std::atomic<float> that I would like to increment by a certain value. However, using fetch_add() on an atomic<float> does not compile and does not seem to be allowed. Is there anyway I can get around this? Here is the code snippet I tried:
std::atomic<float> data(0);
void do_work(){ data.fetch_add(1); }
The error I get is that fetch_add is not a member of atomic<float>
EDIT: Forgot to clarify that I am compiling with g++ version 9.3.0 using -std=c++2a
Floating point atomics are only supported by the C++ library in g++ 10.1 and later. See https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html and search for P0020R6.
Your code compiles fine with g++ 10.2: Try on godbolt

g++ does not include files it says it includes for C++11?

Short version
When I compile even a simple code using a feature of the C++11 standard (the std::stod function), GCC 4.9.1 fails with the following error:
example.cpp: In function 'int main()':
example.cpp:10:18: error: 'stod' is not a member of 'std'
double earth = std::stod (orbits,&sz);
^
example.cpp:11:17: error: 'stod' is not a member of 'std'
double moon = std::stod (orbits.substr(sz));
^
What?
The command I use is g++ -std=c++11 example.cpp.
This is the test code (which compiles fine on other systems):
// stod example from http://www.cplusplus.com/reference/string/stod/
#include <iostream> // std::cout
#include <string> // std::string, std::stod
int main ()
{
std::string orbits ("365.24 29.53");
std::string::size_type sz; // alias of size_t
double earth = std::stod (orbits,&sz);
double moon = std::stod (orbits.substr(sz));
std::cout << "The moon completes " << (earth/moon) << " orbits per Earth year.\n";
return 0;
}
details
I am using a version of GCC 4.9.1 I compiled myself on two different clusters running CentOS 6.5 (I use the modules system on stuff in my home dir since I'm not an admin).
I will call them cluster 1 and cluster 2: cluster 1 is where the failure happens.
The GCCs were compiled in the same way and at the same time, and loaded using identical module files (save for a minor difference in the base path). The installations are, as far as I can easily check, identical (the same include files exist on both clusters, and have the same contents).
The output from g++ -v is the same on both clusters (again, except for the install path):
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/home/andyras/bin/gcc-4.9.1/libexec/gcc/x86_64-unknown-linux-gnu/4.9.1/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../gcc-4.9.1/configure --prefix=/home/andyras/bin/gcc-4.9.1 --enable-languages=c,c++,fortran
Thread model: posix
gcc version 4.9.1 (GCC)
g++ -v using the system GCC gives the same output on both clusters, except on cluster 1 it says it is gcc version 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) and on cluster 2 says gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)
I am trying to debug using g++ -std=c++11 -save-temps -MD example.cpp for more info... this gives some clues, but I don't know where to go from here.
The intermediate (.ii) files on cluster 1 are missing some lines, for example (excerpt from diffing the .ii files):
< # 277 "/opt/gcc-4.9.1/include/c++/4.9.1/cwchar" 3
---
> # 277 "/home/andyras/bin/gcc-4.9.1/include/c++/4.9.1/cwchar" 3
961,963c934,936
< using std::wcstold;
< using std::wcstoll;
< using std::wcstoull;
---
>
>
>
As I interpret it, GCC on both clusters tries to include files like cwchar, but on cluster 1 there are blank lines instead of things being defined. On cluster 2 the stod function is in the intermediate file, but not on cluster 1.
Could it be a preprocessor error?
Now looking at the .d (dependency) files, I also see a concrete difference. There are some files listed on cluster 2 that are not listed on cluster 1. Here is the list (I processed the contents of the .d files to account for the different base paths; // stands in for the install path):
85a86,108
> //gcc-4.9.1/include/c++/4.9.1/ext/string_conversions.h
> //gcc-4.9.1/include/c++/4.9.1/cstdlib
> /usr/include/stdlib.h
> /usr/include/bits/waitflags.h
> /usr/include/bits/waitstatus.h
> /usr/include/sys/types.h
> /usr/include/sys/select.h
> /usr/include/bits/select.h
> /usr/include/bits/sigset.h
> /usr/include/sys/sysmacros.h
> /usr/include/alloca.h
> //gcc-4.9.1/include/c++/4.9.1/cstdio
> /usr/include/libio.h
> /usr/include/_G_config.h
> /usr/include/bits/stdio_lim.h
> /usr/include/bits/sys_errlist.h
> //gcc-4.9.1/include/c++/4.9.1/cerrno
> /usr/include/errno.h
> /usr/include/bits/errno.h
> /usr/include/linux/errno.h
> /usr/include/asm/errno.h
> /usr/include/asm-generic/errno.h
> /usr/include/asm-generic/errno-base.h
I was curious if cpp was looking for includes in all the wrong places, but this seems legit (cpp -v):
#include <...> search starts here:
/home/andyras/bin/gcc-4.9.1/include
/home/andyras/bin/gcc-4.9.1/include/c++/4.9.1/
/home/andyras/bin/gcc-4.9.1/include/c++/4.9.1/x86_64-unknown-linux-gnu/
/home/andyras/bin/gcc-4.9.1/lib/gcc/x86_64-unknown-linux-gnu/4.9.1/include
/usr/local/include
/home/andyras/bin/gcc-4.9.1/lib/gcc/x86_64-unknown-linux-gnu/4.9.1/include-fixed
/usr/include
End of search list.
This has been a very frustrating couple of hours trying to track down the source of the problem. I could, of course, use something like atof(myString.c_str()) instead of std::stod, but I am wondering if there is an underlying issue that will foul up future projects using other bits of C++11.
Any more clues or insight would be very much appreciated.
You have already done all the necessary footwork to determine the root cause. You already know the answer: you have posted clear differences between how custom gcc installs behave on your "cluster 1" and "cluster 2", a non-working and a working build.
So, something is obviously different between these two gcc installs; if one compiles, links, and runs some code, and the other one chokes on the exact same piece of code. Unfortunately, it's hard to pinpoint where things go off the rails. Having built gcc myself before, previously, I can say that gcc is a hellishly difficult, and very fickle package to install. For example, after several days chasing a mysterious failure when linking some C++ code, I ended up chasing it down to gcc picking up the wrong version of binutils, in gcc's configure script, and internally turning off some obscure feature, that eventually manifested itself as a link failure not of gcc, but of stuff that got built with gcc. gcc itself got built, and installed, with nary a complaint, but it was broken.
So, I find it completely unsurprising, and entirely plausible, the proposition that gcc itself got built and installed without an apparent issue, but it's broken, and will choke on valid code, in this fashion.
My guess would be that your busted gcc build is using a broken default include path -- it's looking for headers in /usr/include, instead of your own custom installation directory. That's the most likely answer, but it could really be anything.
Well, you obviously have (like you wrote yourself) two different versoins of gcc (one time 4.4.7-3 and the other 4.4.7-4), and It seems that they have (even though slightly) differences in compiling the code.
As I've read somewhere, the C++11-standard is not yet included completely in all compilers, so this seems to be the cause on the one Cluster. The other has (you might know why) a version where more of the new standard is included and since you want you use exactly this feature I'd recommend installing this version on the other Cluster too.

C++ 11 Threads, Error Pure virtual function called

here is a very minimal C++11 Thread API code that I am trying to compile
#include<iostream>
#include<thread>
using namespace std;
void threadFunction(void)
{
cout<<"hello from thread:";//<<this_thread::get_id()<<endl;
}
int main()
{
std::thread t(threadFunction);
t.join();
return 0;
}
On Compiling this as
g++ thread1.cpp -pthread -std=c++11
I get the following error
pure virtual method called
terminate called without an active exception
Aborted
What wrong, can someone please help
Note that I am compiling this on Beaglebone Black with ARM A8 processor
This is a bug in either libstdc++ or Clang, depending on who you ask. It should work if you are using a version of Clang released after October 2013. What do you see when you run g++ --version?
As a workaround, you could try using this command line instead. I don't guarantee that it would work; please post a comment with your results.
g++ -pthread -std=c++11 -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_{1,2,4} thread1.cpp
Here's the bug report:
http://llvm.org/bugs/show_bug.cgi?id=12730
And here's the official fix to the Clang driver:
https://llvm.org/viewvc/llvm-project?view=revision&revision=191707
I don't know if this was also previously a bug in the GCC driver, and/or whether it's been fixed.
Ran into the same problem on a Raspberry Pi 2 Model B with an ARM Cortex-A7.
Compiled with g++-4.7, turned out the culprit was a compiler flag:
-march=armv7-a
Although clang had a related issue, this is entirely a gcc bug now recorded at: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62100

gcc detecting "subindex out of bound" error

Surprisingly I found gcc can find this error when it compiles C. I simplified the code which still triggers the warning. I post the question for making clear the details of the techniques it uses. Below is my code of file a.c
int main(){
int a[1]={0};
return(a[1]);
}
My gcc version is gcc (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3. When using gcc a.c -Wall, there is no warning; when using gcc -O1 a.c -Wall, there is a warning:
warning: ‘a[1]’ is used uninitialized in this function [-Wuninitialized]
and when using gcc -O2 a.c -Wall (or -O3), there is another warning:
warning: array subscript is above array bounds [-Warray-bounds]
The most surprising thing is that, when I give a[1] a value, then none of the above compiling options gives any warning. There is no warning even when I change the index to a huge number (of course the compiled file offends the operating system and will be kicked out),
int main(){
int a[1]={0};
a[2147483648]=0;
return(a[2147483648]);
}
I think the above phenomenon is more of a function than a bug. I hope someone help me figure out what happens, and/or why the compiler is designed so. Many thanks!
Accessing memory past the end of the array results in undefined behaviour.
gcc is nice enough to go out of its way to detect, and warn you about, some of these errors. However, it is under no obligation to do so, and certainly cannot be expected to catch all such errors.
The compiler is not required to provide diagnostic for this kind of error, but gcc is often able to help; notice that these warnings often arise in part as a byproduct of the static analysis passes done for optimization purposes, which means that, as you noticed, such warnings often depend from the specified optimization level.