When using a global array of structs i have identified the following bug:
1. The struct has two members of any kind
2. when you assing a value to the first member the second member gets overwritten, in fact the next 4 bytes get overwritten
so if you have 4 chars they all get overwritten
3.This only happens if you have a global array struct defined out of scope
4. If the array is of size 1 the bug does not appear, size must be 2 or more
My sscce:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
struct test_s
{
float val ;
int bol ;
} ;
#define LEN 5
struct test_s mystr[LEN] ;
int main( void )
{
for( int i = 0 ; i < LEN ; i += 1 )
{
mystr[i].val = 321.0f ;
mystr[i].bol = 1 ;
}
for( int i = 0 ; i < LEN ; i += 1 )
printf( "\n %f %d" , mystr[i].val , mystr[i].bol ) ;
for( int i = 0 ; i < LEN ; i += 1 )
mystr[i].val = 0.0f ; //set only val to 0
for( int i = 0 ; i < LEN ; i += 1 )
printf( "\n %f %d" , mystr[i].val , mystr[i].bol ) ; //both values get printed as 0, WRONG!
return 0;
}
Output should be http://ideone.com/qWpKPF
321.000000 1
321.000000 1
321.000000 1
321.000000 1
321.000000 1
0.000000 1
0.000000 1
0.000000 1
0.000000 1
0.000000 1
but is
321.000000 1
321.000000 1
321.000000 1
321.000000 1
321.000000 1
0.000000 0
0.000000 0
0.000000 0
0.000000 0
0.000000 0
Can someone please verify this on their version of Pelles IDE.
MY system: Windows 7 32 bit Professional, Service Pack 1 ( Build 7601 ), Pelles Version 7.00.355
The bug goes away with no optimizations.
John
Quote from: JohnF on June 22, 2013, 09:36:57 PM
The bug goes away with no optimizations.
John
Indeed it does, so it is a pelles bug;
i forgot to check for optimizations
Minor update:
If I switch the variable position in struct test_s this i get this output: (with optimizations of course)
321.000000 1
321.000000 1
321.000000 1
321.000000 1
321.000000 1
0.000000 1
0.000000 0
0.000000 0
0.000000 0
0.000000 0
Seems to zeroing whole struct:
for( int i = 0 ; i < LEN ; i += 1 )
mystr[i].val = 0.0f ; //set only val to 0
[0040104F] BFC4904000 mov edi,mystr
[00401054] 31C0 xor eax,eax
[00401056] B928000000 mov ecx,28
[0040105B] F3AA rep stosb
[0040105D] 31DB xor ebx,ebx
The bug comes from static values optimizations, infact if you move your code in a function and pass as parameters the initialization values the compiler doesn.t overwrite struct:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
struct test_s
{
float val ;
int bol ;
} ;
#define LEN 5
struct test_s mystr[LEN] ;
void test(float a, float b)
{
for( int i = 0 ; i < LEN ; i += 1 )
{
//mystr[i].val = 321.0f ;
mystr[i].val = a ;
mystr[i].bol = 1 ;
}
for( int i = 0 ; i < LEN ; i += 1 )
printf( "\n %f %d" , mystr[i].val , mystr[i].bol ) ;
for( int i = 0 ; i < LEN ; i += 1 )
//mystr[i].val = 0.1f ; //set only val to 0
mystr[i].val = b ; //set only val to 0
for( int i = 0 ; i < LEN ; i += 1 )
printf( "\n %f %d" , mystr[i].val , mystr[i].bol ) ; //both values get printed as 0, WRONG!
}
int main( void )
{
test(321.0f, 0.0f);
return 0;
}
Below I report a code piece from my FtypeLib where something similiar happens:
#pragma optimize(none)
/*+@@fnc@@----------------------------------------------------------------*//*!
\brief DynStrFmtAppend
\date Created on Wed Apr 10 22:05:13 2013
\date Modified on Wed Apr 10 22:05:13 2013
\*//*-@@fnc@@----------------------------------------------------------------*/
_FMT_2_3 LPDYNSTR __cdecl DynStrFmtAppend (LPDYNSTR *dynstr, DWORD *cChr, const WCHAR *Fmt, ...)
{
int cLen = 0;
va_list ap;
va_start(ap, Fmt);
cLen = vFmtStrTextLen(Fmt, ap) + 1;
if (cChr)
*cChr = cLen;
if (!dynstr)
return NULL;
_LPDYNSTR p = GETDYNSTRPTR(*dynstr);
if (!p)
return NULL;
p = ResizeDynStr(p, cLen);
if (!p)
{
*dynstr = NULL;
return NULL;
}
vswprintf((p->str)+wcslen(p->str), cLen, Fmt, ap);
va_end(ap);
*dynstr = GETDYNSTRSTR(p);
/*
* COMPILER BUG REPORT.
* When optimizations are on the following line reports always the former string length!
* That's why the compiler makes 2 wrong assumptions:
* 1. That nobody modified the string from the previous 'wcslen' calculation.
* But 'vswprintf' does.
* 2. That the register 'edi', holding the former wcslen(p->str), has not been
* changed before reuse.
*/
p->len = wcslen(p->str) + 1;
return GETDYNSTRSTR(p);
}
#pragma optimize()
Yes advanced optimizations have some bugs :'(
Is there any chance that this bug will get fixed, or in other words is pelles still being supported by the author?
As far as we know he is still supporting even if we don't have any date for updates.