https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90611

--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Aaron Greig from comment #0)
> Created attachment 46403 [details]
> cpp file that triggers the bug
> 
> I am finding that when I compile the attached file, with the following
> command:
> g++-8 -m32 -std=c++11 -msse -O3 repro.cpp -o repro -Wall -Wextra
> -fno-strict-aliasing -fwrapv
> I get this output:
> repro.cpp: In function ‘int main(int, char**)’:
> repro.cpp:13:14: warning: unused parameter ‘argc’ [-Wunused-parameter]
>  int main(int argc, char** argv) {
>           ~~~~^~~~
> repro.cpp:13:27: warning: unused parameter ‘argv’ [-Wunused-parameter]
>  int main(int argc, char** argv) {
>                     ~~~~~~~^~~~

You know you can just declare int main() or int main(int, char**) to have a
reproducer that doesn't give any warnings, right?

> and when I run the resulting binary on a 32-bit system I get an immediate
> segfault. This seems to be due to a movaps instruction generating a general
> protection exception (see https://www.felixcloutier.com/x86/movaps) because
> the address it is loading from isn't aligned to 16 bytes. The minimal
> command I have found to reproduce this is
> g++-8 -m32 -std=c++11 -msse -O3 repro.cpp -o repro
> the output of g++-8 --version is:
> g++-8 (Ubuntu 8.3.0-6ubuntu1~18.04) 8.3.0
> The system I run the binary on is a virtualbox VM with 32-bit Ubuntu 16.04
> installed on it. I can reproduce this bug in the same way by compiling with
> that system's installed g++, version:
> g++ (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609

There are a few issues interacting here.

1) Glibc now (since version 2.26) returns 16-byte aligned memory from malloc,
so  this Just Works with a newer glibc. But if your code needed more than
16-byte alignment it would still fail even with a newer glibc, so let's assume
you needed 32-byte alignment...

2) In C++11 and C++14 the standard library does not support overaligned types,
it only supports the alignments that malloc supports. But C++17 added extended
alignment support to the standard library, so compiling with -std=c++17 or
-std=gnu++17 should make extended alignments work. You can also enable extended
alignment support for C++11 and C++14 with the -faligned-new flag. However ...

3) GCC assumes glibc malloc always returns 16-byte aligned memory, even if you
have glibc 2.25 or older, which only returns 8-byte alignment for x86. That
means GCC thinks 16-byte is not extended, but malloc disagrees. I'm trying to
fix that, see PR 90569.

4) To workaround PR 90569 you can use the -faligned-new=8 which tells GCC that
any alignment higher than 8 should be considered an extended alignment, and so
needs special handling (which means it doesn't use malloc, so isn't affected by
old versions of malloc only returning 8-byte alignment).

In summary: With a new glibc and C++17 extended alignments just work
automatically. For older glibc and/or C++11 you can use -faligned-new=8 to make
it work.

I think there is no GCC bug here (except for PR 90569 which I'm already working
on).

Reply via email to