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.langlois@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 <olivier@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.