On 2013-05-13 18:20:05, LANGLOIS Olivier PIS -EXT wrote:
> Date: Mon, 13 May 2013 18:20:05 +0000
> From: LANGLOIS Olivier PIS -EXT <olivier.pis.langl...@transport.alstom.com>
> To: "General Discussion about Arch Linux (arch-general@archlinux.org)"
> <arch-general@archlinux.org>
> Subject: [arch-general] gcc: loop do not terminate
>
> I have just been hit by something:
>
> lano1106@hpmini ~/dev/gcc-test $ g++ --version
> g++ (GCC) 4.8.0 20130502 (prerelease)
> Copyright (C) 2013 Free Software Foundation, Inc.
> This is free software; see the source for copying conditions. There is NO
> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
>
> lano1106@hpmini ~/dev/gcc-test $ g++ -O2 -o test1 test1.cpp test1_init.cpp
> lano1106@hpmini ~/dev/gcc-test $ ./test1
> item 0
> a: 1
> lano1106@hpmini ~/dev/gcc-test $ g++ -O1 -o test1 test1.cpp test1_init.cpp
> lano1106@hpmini ~/dev/gcc-test $ ./test1
> item 0
> a: 1
> lano1106@hpmini ~/dev/gcc-test $ g++ -O0 -o test1 test1.cpp test1_init.cpp
> lano1106@hpmini ~/dev/gcc-test $ ./test1
> item 0
> a: 1
> item 1
> a: 2
> lano1106@hpmini ~/dev/gcc-test $ cat test1.h
>
> struct A
> {
> int a;
> int b;
> int c;
> };
>
> struct B
> {
> int numelem;
> /*
> * Old C trick to define a dynamically sizable array just by
> allocating
> * sizeof(B) + (numelem-1)*sizeof(A) memory.
> */
> A item[1];
> };
>
> void initArr(B *p);
>
> lano1106@hpmini ~/dev/gcc-test $ cat test1_init.cpp
> #include "test1.h"
>
> void initArr(B *p)
> {
> p->numelem = 2;
> p->item[0].a = 1;
> p->item[1].a = 2;
> }
If this function initArr() is moved to the same cpp file of main(),
all optimization level get the same result.
>
> lano1106@hpmini ~/dev/gcc-test $ cat test1.cpp
> /*
> * Author: Olivier Langlois <oliv...@trillion01.com>
> *
> * Purpose: Small test to highlight gcc optimization bug
> */
>
> #include <stdio.h>
> #include <string.h>
> #include "test1.h"
>
> /*
> * Create a B array with the intent of only using the first item.
> * The 19 other items sole purpose is to create a buffer large enough
> * to accomodate A array needs.
> */
> #define MAXBLEN 20
>
> int main(int argc, char *argv[])
> {
> B arr[MAXBLEN];
> memset(arr,0,sizeof(arr));
>
> initArr(arr);
>
> for( int i = 0; i < arr[0].numelem; ++i )
> {
> printf( "item %d\n"
> " a: %d\n",
> i,
> arr[0].item[i].a);
> }
>
> return 0;
> }
>
> From gcc website, this is not a bug:
>
> Loops do not terminate
>
> This is often caused by out-of-bound array accesses or by signed integer
> overflow which both result in undefined behavior according to the ISO C
> standard. For example
>
> int
> SATD (int* diff, int use_hadamard)
> {
> int k, satd = 0, m[16], dd, d[16];
> ...
> for (dd=d[k=0]; k<16; dd=d[++k])
> satd += (dd < 0 ? -dd : dd);
>
> accesses d[16] before the loop is exited with the k<16 check. This causes
> the compiler to optimize away the exit test because the new value of k must
> be in the range [0, 15] according to ISO C.
>
> GCC starting with version 4.8 has a new option
> -fno-aggressive-loop-optimizations that may help here. If it does, then this
> is a clear sign that your code is not conforming to ISO C and it is not a GCC
> bug.
>
> I am surprised that I didn't hit the problem before but I am seriously
> considering using '-fno-aggressive-loop-optimizations' in my own
> makepkg.conf. I just want to test others feeling on this discovery to see if
> it wouldn't be a good idea to make the switch standard in Arch...
>
>
> ________________________________
> CONFIDENTIALITY : This e-mail and any attachments are confidential and may be
> privileged. If you are not a named recipient, please notify the sender
> immediately and do not disclose the contents to another person, use it for
> any purpose or store or copy the information in any medium.