Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   [MUDFLAP] Is sizeof(ARRAY[0]) equivalent to sizeof(*ARRAY) ? (http://www.velocityreviews.com/forums/t956348-mudflap-is-sizeof-array-0-equivalent-to-sizeof-array.html)

m.labanowicz@gmail.com 01-09-2013 03:26 PM

[MUDFLAP] Is sizeof(ARRAY[0]) equivalent to sizeof(*ARRAY) ?
 
Hi,

I'm looking for the reason of the MUDFLAP violation
on my 'BIG' C project (no possibility to show),
system: Ubuntu:12.04, gcc:4.6.3.

NOTE: The same 'BIG' project has been successfully executed
on my old system: Ubuntu:10.04, gcc-(version don't remember).
Mudflap was silent.

My investigation shows that there
are called some functions before 'main', like:
_GLOBAL__sub_I_00099_0_<org_fun_name>

Currently MUDFLAP violates before calling 'main' in
_GLOBAL__sub_I_00099_0_<my_function>

if I change source code of <my_function>
from sizeof(*ARRAY)
to sizeof(ARRAY[0])
then violation source shifts to another
_GLOBAL__sub_I_00099_0_... function.

But this algoritm failed in case MUDFLAP violates
at function that has no usage of sizeof(ARRAY) operator.

Common for the all functions that MUDFLAP violates is the
static const ARRAY usage, example:

/*--EXAMPLE-BEG----------------*/
01: extern unsigned my_function_check(unsigned a, unsigned b, unsigned c);
02: void my_function(void)
03: {
04: unsigned const SCALE [] = { 0, 1, 2 };
05: unsigned const TOSTEP [][2] = {
06: { 10, 1},
07: { 100, 8}
08: };
09: unsigned s = sizeof(SCALE) / sizeof(SCALE[0]);
10: while (s--)
11: {
12: unsigned i = 0;
13: while (i < (sizeof(TOSTEP) / sizeof(TOSTEP[0])))
14: {
15: unsigned current = 0;
16: unsigned value = 0;
17: current = my_function_check(SCALE[s], TOSTEP[i][0], value);
18: if (current)
19: {
20: return;
21: }
22: ++i;
23: }
24: }
25: }
/*--EXAMPLE-BEG----------------*/

In this example I have not found any reason of
violate before calling the main.

There is amazing difference that depends
on usage of the sizeof operator:

--[TEST-BEG]------------------------------
+ uname -a
Linux ldrlinux 3.2.0-35-generic-pae #55-Ubuntu SMP Wed Dec 5 18:04:39 UTC 2012 i686 i686 i386 GNU/Linux
+ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 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.

+ gawk '{printf("%02u: %s\n", NR, $0);}'
+ cat bar.c
01: #include <stddef.h> /* size_t */
02: static int const BAR [] = {0,1,2,3,4};
03: size_t bar_element_sizeof(void) {
04: #if ASTERISK
05: return sizeof(*BAR);
06: #else
07: return sizeof(BAR[0]);
08: #endif
09: }
+ gcc -W -Wall -ansi -pedantic -Werror -fmudflap -DnotASTERISK -c bar.c -o bar_notASTERISK.o
+ gcc -W -Wall -ansi -pedantic -Werror -fmudflap -DASTERISK -c bar.c -o bar_ASTERISK.o
+ objdump -d bar_notASTERISK.o
+ objdump -d bar_ASTERISK.o
+ diff bar_notASTERISK.S bar_ASTERISK.S
2c2
< bar_notASTERISK.o: file format elf32-i386
---
> bar_ASTERISK.o: file format elf32-i386

17c17
< d: 83 ec 08 sub $0x8,%esp
---
> d: 83 ec 18 sub $0x18,%esp

19,20c19,28
< 15: c9 leave
< 16: c3 ret
---
> 15: c7 44 24 0c 14 00 00 movl $0x14,0xc(%esp)
> 1c: 00
> 1d: c7 44 24 08 04 00 00 movl $0x4,0x8(%esp)
> 24: 00
> 25: c7 44 24 04 14 00 00 movl $0x14,0x4(%esp)
> 2c: 00
> 2d: c7 04 24 00 00 00 00 movl $0x0,(%esp)
> 34: e8 fc ff ff ff call 35 <_GLOBAL__sub_I_00099_0_bar_element_sizeof+0x2b>
> 39: c9 leave
> 3a: c3 ret

--[TEST-EOF]------------------------------

Is there any clear reason of such difference ?

Best Regards

--
Maciek

James Kuyper 01-09-2013 04:30 PM

Re: [MUDFLAP] Is sizeof(ARRAY[0]) equivalent to sizeof(*ARRAY) ?
 
On 01/09/2013 10:26 AM, m.labanowicz@gmail.com wrote:
....
> + cat bar.c
> 01: #include <stddef.h> /* size_t */
> 02: static int const BAR [] = {0,1,2,3,4};
> 03: size_t bar_element_sizeof(void) {
> 04: #if ASTERISK
> 05: return sizeof(*BAR);
> 06: #else
> 07: return sizeof(BAR[0]);
> 08: #endif
> 09: }
> + gcc -W -Wall -ansi -pedantic -Werror -fmudflap -DnotASTERISK -c bar.c -o bar_notASTERISK.o
> + gcc -W -Wall -ansi -pedantic -Werror -fmudflap -DASTERISK -c bar.c -o bar_ASTERISK.o
> + objdump -d bar_notASTERISK.o
> + objdump -d bar_ASTERISK.o


As far as C is concerned, with the above definition for BAR,
sizeof(*BAR) and sizeof(BAR[0]) are exactly equivalent (and the
parentheses are unnecessary). As implied by the extensive use of
"mudflap" and "MUDFLAP" throughout your message, this is a problem
specific to gcc's -fmudflap option - without that option, gcc generates
identical object code whether or not ASTERISK is #defined. Therefore,
the best place to get answers to this question are on a forum specific
to gcc. I don't know the answer.
--
James Kuyper

Eric Sosman 01-09-2013 04:58 PM

Re: [MUDFLAP] Is sizeof(ARRAY[0]) equivalent to sizeof(*ARRAY) ?
 
On 1/9/2013 10:26 AM, m.labanowicz@gmail.com wrote:
> I'm looking for the reason of the MUDFLAP violation
> on my 'BIG' C project (no possibility to show),
> system: Ubuntu:12.04, gcc:4.6.3.


I don't have mudflap available and can't help with it, so
my comments are limited to the C aspects of the question. I hope
they may be of some help anyhow ...

> Currently MUDFLAP violates before calling 'main' in
> _GLOBAL__sub_I_00099_0_<my_function>


Are you sure this is a C program, and not a C++ program?
In a C program, there's no way for any of your own code to run
before main() is called, whereas in C++ some of your code may
run during pre-main() initialization. I suppose the mudflap
instrumentation might do some non-C-ish things, but ...

> if I change source code of <my_function>
> from sizeof(*ARRAY)
> to sizeof(ARRAY[0])
> then violation source shifts to another
> _GLOBAL__sub_I_00099_0_... function.


From the perspective of the C language, the two expressions
have identical meaning. That's because of the way C defines the
array subscript operator, in 6.5.2.1p2: "The definition of the
subscript operator [] is that E1[E2] is identical to (*((E1)+(E2)))."
In your case `E1' and `E2' are `ARRAY' and `0', so your second
expression is identical to `sizeof((*((ARRAY)+(0))))', which is
equivalent to `sizeof *ARRAY' after simplification.

Two points, though. First, the expression that is the operand
of `sizeof' isn't evaluated at all (not in this case, anyhow);
all that matters is the expression's type. Second, the compiler
is not required to evaluate two equivalent expressions the same
way; it's perfectly all right for the compiler to emit different
code for `x = 42' and for `x = 40 + 2', or even for `x = 052'.
C requires that `sizeof(*ARRAY)' and `sizeof(ARRAY[0])' produce
the same type and value, but does not require that they use the
same mechanisms to generate the result.

> There is amazing difference that depends
> on usage of the sizeof operator:
> [... sizeof(*BAR) and sizeof(BAR[0]) generate different code ...]
> Is there any clear reason of such difference ?


None that I can see -- although, as explained above, C does
not dictate any particular style of code generation. My wild
guess is that since mudflap is concerned with array bounds
checking, the difference may arise from the way mudflap adds
instrumentation: Perhaps it recognizes one construct as an array-
using expression but not the other, and therefore instruments
them differently.

--
Eric Sosman
esosman@comcast-dot-net.invalid

Keith Thompson 01-09-2013 07:22 PM

Re: [MUDFLAP] Is sizeof(ARRAY[0]) equivalent to sizeof(*ARRAY) ?
 
Eric Sosman <esosman@comcast-dot-net.invalid> writes:
> On 1/9/2013 10:26 AM, m.labanowicz@gmail.com wrote:

[...]
>> There is amazing difference that depends
>> on usage of the sizeof operator:
>> [... sizeof(*BAR) and sizeof(BAR[0]) generate different code ...]
>> Is there any clear reason of such difference ?

>
> None that I can see -- although, as explained above, C does
> not dictate any particular style of code generation. My wild
> guess is that since mudflap is concerned with array bounds
> checking, the difference may arise from the way mudflap adds
> instrumentation: Perhaps it recognizes one construct as an array-
> using expression but not the other, and therefore instruments
> them differently.


Mudflap probably shouldn't be instrumenting code that's an argument
to sizeof in the first place, since it's never executed (barring
VLAs).

For example, given `int arr[10];` this expression: `sizeof arr[1000]`
is perfectly valid, and evaluates to the same value as `sizeof
(int)`.

"My code is fine, it must be a bug in the development tools" is
not the first thought you should have, but in this case it's a
distinct possibility.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Shao Miller 01-09-2013 07:39 PM

Re: [MUDFLAP] Is sizeof(ARRAY[0]) equivalent to sizeof(*ARRAY) ?
 
On 1/9/2013 10:26, m.labanowicz@gmail.com wrote:
>
> I'm looking for the reason of the MUDFLAP violation
> on my 'BIG' C project (no possibility to show),
> system: Ubuntu:12.04, gcc:4.6.3.
>


You don't need to show the big project, but it might help if you showed
the violation!

Are you linking with libmudflap by using '-lmudflap' with GCC?

> NOTE: The same 'BIG' project has been successfully executed
> on my old system: Ubuntu:10.04, gcc-(version don't remember).
> Mudflap was silent.
>
> My investigation shows that there
> are called some functions before 'main', like:
> _GLOBAL__sub_I_00099_0_<org_fun_name>
>
> Currently MUDFLAP violates before calling 'main' in
> _GLOBAL__sub_I_00099_0_<my_function>
>
> if I change source code of <my_function>
> from sizeof(*ARRAY)
> to sizeof(ARRAY[0])
> then violation source shifts to another
> _GLOBAL__sub_I_00099_0_... function.
>


That suggests to me the possibility that you are running afoul of
undefined behaviour _before_ coming across your 'sizeof' usage, because
if you run afoul of undefined behaviour, anything can happen and the
precise nature of the weirdness can depend on things that _shouldn't_
make a difference, such as the difference between your two 'sizeof's.

> But this algoritm failed in case MUDFLAP violates
> at function that has no usage of sizeof(ARRAY) operator.
>


That's quite possible, since the undefined behaviour might be invoked
_before_ the 'sizeof' use. That's the thing about undefined
behaviour... While trying to track it down, you might think it's
because of "thing #1". (But it's not.) Then you change "thing #1" and
find that things change! (But you haven't fixed the undefined
behaviour.) But then later it looks like "thing #2" has a problem.

> Common for the all functions that MUDFLAP violates is the
> static const ARRAY usage, example:
>
> /*--EXAMPLE-BEG----------------*/
> 01: extern unsigned my_function_check(unsigned a, unsigned b, unsigned c);
> 02: void my_function(void)
> 03: {
> 04: unsigned const SCALE [] = { 0, 1, 2 };
> 05: unsigned const TOSTEP [][2] = {
> 06: { 10, 1},
> 07: { 100, 8}
> 08: };
> 09: unsigned s = sizeof(SCALE) / sizeof(SCALE[0]);
> 10: while (s--)
> 11: {
> 12: unsigned i = 0;
> 13: while (i < (sizeof(TOSTEP) / sizeof(TOSTEP[0])))
> 14: {
> 15: unsigned current = 0;
> 16: unsigned value = 0;
> 17: current = my_function_check(SCALE[s], TOSTEP[i][0], value);
> 18: if (current)
> 19: {
> 20: return;
> 21: }
> 22: ++i;
> 23: }
> 24: }
> 25: }
> /*--EXAMPLE-BEG----------------*/
>
> In this example I have not found any reason of
> violate before calling the main.
>
> There is amazing difference that depends
> on usage of the sizeof operator:
>


It's not that amazing, if undefined behaviour is involved.

> --[TEST-BEG]------------------------------
> + uname -a
> Linux ldrlinux 3.2.0-35-generic-pae #55-Ubuntu SMP Wed Dec 5 18:04:39 UTC 2012 i686 i686 i386 GNU/Linux
> + gcc --version
> gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
> Copyright (C) 2011 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.
>
> + gawk '{printf("%02u: %s\n", NR, $0);}'
> + cat bar.c
> 01: #include <stddef.h> /* size_t */
> 02: static int const BAR [] = {0,1,2,3,4};
> 03: size_t bar_element_sizeof(void) {
> 04: #if ASTERISK
> 05: return sizeof(*BAR);
> 06: #else
> 07: return sizeof(BAR[0]);
> 08: #endif
> 09: }
> + gcc -W -Wall -ansi -pedantic -Werror -fmudflap -DnotASTERISK -c bar.c -o bar_notASTERISK.o
> + gcc -W -Wall -ansi -pedantic -Werror -fmudflap -DASTERISK -c bar.c -o bar_ASTERISK.o
> + objdump -d bar_notASTERISK.o
> + objdump -d bar_ASTERISK.o
> + diff bar_notASTERISK.S bar_ASTERISK.S
> 2c2
> < bar_notASTERISK.o: file format elf32-i386
> ---
>> bar_ASTERISK.o: file format elf32-i386

> 17c17
> < d: 83 ec 08 sub $0x8,%esp
> ---
>> d: 83 ec 18 sub $0x18,%esp

> 19,20c19,28
> < 15: c9 leave
> < 16: c3 ret
> ---
>> 15: c7 44 24 0c 14 00 00 movl $0x14,0xc(%esp)
>> 1c: 00
>> 1d: c7 44 24 08 04 00 00 movl $0x4,0x8(%esp)
>> 24: 00
>> 25: c7 44 24 04 14 00 00 movl $0x14,0x4(%esp)
>> 2c: 00
>> 2d: c7 04 24 00 00 00 00 movl $0x0,(%esp)
>> 34: e8 fc ff ff ff call 35 <_GLOBAL__sub_I_00099_0_bar_element_sizeof+0x2b>
>> 39: c9 leave
>> 3a: c3 ret

> --[TEST-EOF]------------------------------
>
> Is there any clear reason of such difference ?
>


Yes. The difference is fully permitted, and even useful.

Furthermore, if the undefined behaviour theory is correct, whatever is
going wrong is simply accidentally running into this difference, but the
_difference_ is not the _cause_ of the undefined behaviour, surely.

I'd suggest reviewing _all_ code that is executed _before_ the first
mudflap violation.

- Shao Miller

m.labanowicz@gmail.com 01-10-2013 10:40 AM

Re: [MUDFLAP] Is sizeof(ARRAY[0]) equivalent to sizeof(*ARRAY) ?
 
Ok, after long investigation I have successfully prepared simple C program that illustrates the issue:
3 files:
- bar.h
- bar.c
- main.c

------------[TEST-BEG]-------------------------
+ gawk '{printf("%02u: %s\n", NR, $0);}' bar.h
01: typedef struct
02: {
03: char const * name;
04: int val;
05: } bar_cfg_t;
06: int bar_fun(void);
+ gawk '{printf("%02u: %s\n", NR, $0);}' bar.c
01: #include "bar.h"
02: #include <stddef.h> /* size_t */
03: int bar_fun(void)
04: {
05: int result = 0;
06: bar_cfg_t bar_cfg [] =
07: {
08: {"@", 0},
09: {"#", 0},
10: {"0", 0},
11: {"1", 0},
12: {"2", 0},
13: {"3", 0},
14: {"4", 0},
15: {"5", 0},
16: #ifdef WORKAROUND_FOR_MUDFLAP
17: {"6", 0},
18: #endif
19: {"7", 0}
20: };
21: bar_cfg_t * bc = bar_cfg;
22: size_t i = 0;
23: while (i++ < (sizeof(bar_cfg) / sizeof(bar_cfg[0])))
24: {
25: bc->val = 123 + (unsigned)(bc->name[0]);
26: result += bc->val;
27: ++bc;
28: }
29: return result;
30: }
+ gawk '{printf("%02u: %s\n", NR, $0);}' main.c
01: #include <stdio.h> /* printf, size_t */
02: #include <stdlib.h> /* EXIT_SUCCESS */
03: #include "bar.h"
04: static int foo_fun(void)
05: {
06: int result = 0;
07: unsigned int const TOSTEP [][2] =
08: {
09: { 100u, 1u},
10: { 100u, 8u},
11: { 0x2333445u, 123344u},
12: { 0x2333445u, 1233446u},
13: {0x00BFC000u, 0x20000u},
14: {0x00FFC000u, 0x20000u},
15: {0x01FFC000u, 0x20000u},
16: {0x02FFC000u, 0x20000u},
17: {0x06FFC000u, 0x10000u},
18: {0x0DFFC000u, 0x10000u}
19: };
20: size_t i = 0;
21: while (i < (sizeof(TOSTEP) / sizeof(TOSTEP[0])))
22: {
23: result = TOSTEP[i][0] + TOSTEP[i][1];
24: i++;
25: }
26: return result;
27: }
28: int main(void)
29: {
30: printf("Hello World !\r\n");
31: printf("foo_fun = %d\r\n", foo_fun());
32: printf("bar_fun = %d\r\n", bar_fun());
33: return EXIT_SUCCESS;
34: }
+ gcc -ansi -pedantic -Wall -W -Werror -fmudflap -c bar.c
+ gcc -ansi -pedantic -Wall -W -Werror -fmudflap -c main.c
+ gcc -Wl,-Map,a.map main.o bar.o -lmudflap
+ MUDFLAP_OPTIONS=-mode-check -viol-nop -verbose-trace -internal-checking -print-leaks -check-initialization -verbose-violations
+ ./a.out
01: *******
02: mudflap violation 1 (register): time=1357813939.099625 ptr=0xbfe56c28 size=72
03: pc=0xb767685e
04: /usr/lib/i386-linux-gnu/libmudflap.so.0(__mf_register+0x3e) [0xb767685e]
05: ./a.out() [0x8048ce0]
06: ./a.out() [0x8048d42]
07: Nearby object 1: checked region begins 8B into and ends 79B into
08: mudflap object 0x8cbf1e8: name=`constant'
09: bounds=[0xbfe56c20,0xbfe56c6f] size=80 area=static check=0r/0w liveness=0
10: alloc time=1357813939.099612 pc=0xb767685e
11: number of nearby objects: 1
12: mf: alloca stack level 0xbfe56b18
13: Hello World !
14: foo_fun = 234930176
15: bar_fun = 1564
16: *******
17: mudflap violation 2 (unregister): time=1357813939.100370 ptr=0x8cbfa20 size=0
18: pc=0xb76763d6
19: number of nearby objects: 0
20: number of leaked objects: 0
-----[with: WORKAORUND_FOR_MUDFLAP]------------
+ rm -fr bar.o main.o a.map a.out
+ gcc -ansi -pedantic -Wall -W -Werror -fmudflap -DWORKAROUND_FOR_MUDFLAP=1 -c bar.c
+ gcc -ansi -pedantic -Wall -W -Werror -fmudflap -c main.c
+ gcc -Wl,-Map,a.map main.o bar.o -lmudflap
+ MUDFLAP_OPTIONS=-mode-check -viol-nop -verbose-trace -internal-checking -print-leaks -check-initialization -verbose-violations
+ ./a.out
01: mf: harmless duplicate reg 0xbfe45950-0xbfe4599f `constant'
02: mf: alloca stack level 0xbfe45848
03: Hello World !
04: foo_fun = 234930176
05: bar_fun = 1741
06: number of leaked objects: 0
------------[TEST-EOF]-------------------------

Please note, that after applying additional element to array
the issue has gone.

So, if this is valid ANSI-C program then this
is an issue connected to GCC/MUDFLAP.

--
Maciej Labanowicz

Shao Miller 01-10-2013 01:31 PM

Re: [MUDFLAP] Is sizeof(ARRAY[0]) equivalent to sizeof(*ARRAY) ?
 
On 1/10/2013 05:40, m.labanowicz@gmail.com wrote:
> Ok, after long investigation I have successfully prepared simple C program that illustrates the issue:
> 3 files:
> - bar.h
> - bar.c
> - main.c
>
> ------------[TEST-BEG]-------------------------
> + gawk '{printf("%02u: %s\n", NR, $0);}' bar.h
> 01: typedef struct
> 02: {
> 03: char const * name;
> 04: int val;
> 05: } bar_cfg_t;
> 06: int bar_fun(void);


Maybe add a helper macro in here:

#if USE_ASTERISK
# define Countof(array) (sizeof (array) / sizeof *(array))
#else
# define Countof(array) (sizeof (array) / sizeof (array)[0])
#endif

> + gawk '{printf("%02u: %s\n", NR, $0);}' bar.c
> 01: #include "bar.h"
> 02: #include <stddef.h> /* size_t */
> 03: int bar_fun(void)
> 04: {
> 05: int result = 0;
> 06: bar_cfg_t bar_cfg [] =
> 07: {
> 08: {"@", 0},
> 09: {"#", 0},
> 10: {"0", 0},
> 11: {"1", 0},
> 12: {"2", 0},
> 13: {"3", 0},
> 14: {"4", 0},
> 15: {"5", 0},
> 16: #ifdef WORKAROUND_FOR_MUDFLAP
> 17: {"6", 0},
> 18: #endif
> 19: {"7", 0}
> 20: };
> 21: bar_cfg_t * bc = bar_cfg;
> 22: size_t i = 0;
> 23: while (i++ < (sizeof(bar_cfg) / sizeof(bar_cfg[0])))
> 24: {
> 25: bc->val = 123 + (unsigned)(bc->name[0]);
> 26: result += bc->val;
> 27: ++bc;
> 28: }
> 29: return result;
> 30: }


Note that 'i' is being used for iteration over 'bar_cfg', but by line
29, its index is _two_past_ the array. That's worth a bounds-checking
diagnostic, would you agree?

I don't know why you're not using a 'for' loop:

/* Circa line 22 */
size_t i;

for (i = 0; i < Countof(bar_cfg); ++i)
{
bc->val = 123 + (unsigned)(bc->name[0]);
result += bc->val;
++bc;
}
return result;
}

> + gawk '{printf("%02u: %s\n", NR, $0);}' main.c
> 01: #include <stdio.h> /* printf, size_t */
> 02: #include <stdlib.h> /* EXIT_SUCCESS */
> 03: #include "bar.h"
> 04: static int foo_fun(void)
> 05: {
> 06: int result = 0;
> 07: unsigned int const TOSTEP [][2] =
> 08: {
> 09: { 100u, 1u},
> 10: { 100u, 8u},
> 11: { 0x2333445u, 123344u},
> 12: { 0x2333445u, 1233446u},
> 13: {0x00BFC000u, 0x20000u},
> 14: {0x00FFC000u, 0x20000u},
> 15: {0x01FFC000u, 0x20000u},
> 16: {0x02FFC000u, 0x20000u},
> 17: {0x06FFC000u, 0x10000u},
> 18: {0x0DFFC000u, 0x10000u}
> 19: };
> 20: size_t i = 0;
> 21: while (i < (sizeof(TOSTEP) / sizeof(TOSTEP[0])))
> 22: {
> 23: result = TOSTEP[i][0] + TOSTEP[i][1];
> 24: i++;
> 25: }
> 26: return result;


/* Circa line 20 */
size_t i;

for (i = 0; i < Countof(TOSTEP); ++i)
result = TOSTEP[i][0] + TOSTEP[i][1];

return result;

> 27: }
> 28: int main(void)
> 29: {
> 30: printf("Hello World !\r\n");
> 31: printf("foo_fun = %d\r\n", foo_fun());
> 32: printf("bar_fun = %d\r\n", bar_fun());
> 33: return EXIT_SUCCESS;
> 34: }
> + gcc -ansi -pedantic -Wall -W -Werror -fmudflap -c bar.c
> + gcc -ansi -pedantic -Wall -W -Werror -fmudflap -c main.c
> + gcc -Wl,-Map,a.map main.o bar.o -lmudflap
> + MUDFLAP_OPTIONS=-mode-check -viol-nop -verbose-trace -internal-checking -print-leaks -check-initialization -verbose-violations
> + ./a.out
> 01: *******
> 02: mudflap violation 1 (register): time=1357813939.099625 ptr=0xbfe56c28 size=72
> 03: pc=0xb767685e
> 04: /usr/lib/i386-linux-gnu/libmudflap.so.0(__mf_register+0x3e) [0xb767685e]
> 05: ./a.out() [0x8048ce0]
> 06: ./a.out() [0x8048d42]
> 07: Nearby object 1: checked region begins 8B into and ends 79B into
> 08: mudflap object 0x8cbf1e8: name=`constant'
> 09: bounds=[0xbfe56c20,0xbfe56c6f] size=80 area=static check=0r/0w liveness=0
> 10: alloc time=1357813939.099612 pc=0xb767685e
> 11: number of nearby objects: 1
> 12: mf: alloca stack level 0xbfe56b18
> 13: Hello World !
> 14: foo_fun = 234930176
> 15: bar_fun = 1564
> 16: *******
> 17: mudflap violation 2 (unregister): time=1357813939.100370 ptr=0x8cbfa20 size=0
> 18: pc=0xb76763d6
> 19: number of nearby objects: 0
> 20: number of leaked objects: 0
> -----[with: WORKAORUND_FOR_MUDFLAP]------------
> + rm -fr bar.o main.o a.map a.out
> + gcc -ansi -pedantic -Wall -W -Werror -fmudflap -DWORKAROUND_FOR_MUDFLAP=1 -c bar.c
> + gcc -ansi -pedantic -Wall -W -Werror -fmudflap -c main.c
> + gcc -Wl,-Map,a.map main.o bar.o -lmudflap
> + MUDFLAP_OPTIONS=-mode-check -viol-nop -verbose-trace -internal-checking -print-leaks -check-initialization -verbose-violations
> + ./a.out
> 01: mf: harmless duplicate reg 0xbfe45950-0xbfe4599f `constant'
> 02: mf: alloca stack level 0xbfe45848
> 03: Hello World !
> 04: foo_fun = 234930176
> 05: bar_fun = 1741
> 06: number of leaked objects: 0
> ------------[TEST-EOF]-------------------------
>
> Please note, that after applying additional element to array
> the issue has gone.
>
> So, if this is valid ANSI-C program then this
> is an issue connected to GCC/MUDFLAP.
>


MUDFLAP can diagnose stuff that's permitted by C90, such as warning you
that an index used for iteration has gone too far. Usually you want to
index one-past an array, at most. Do the 'for' loops have any problems?

- Shao Miller

Shao Miller 01-10-2013 01:49 PM

Re: [MUDFLAP] Is sizeof(ARRAY[0]) equivalent to sizeof(*ARRAY) ?
 
On 1/10/2013 08:31, Shao Miller wrote:
> On 1/10/2013 05:40, m.labanowicz@gmail.com wrote:
>> 21: bar_cfg_t * bc = bar_cfg;
>> 22: size_t i = 0;
>> 23: while (i++ < (sizeof(bar_cfg) / sizeof(bar_cfg[0])))
>> 24: {
>> 25: bc->val = 123 + (unsigned)(bc->name[0]);
>> 26: result += bc->val;
>> 27: ++bc;
>> 28: }
>> 29: return result;
>> 30: }

>
> Note that 'i' is being used for iteration over 'bar_cfg', but by line
> 29, its index is _two_past_ the array. That's worth a bounds-checking
> diagnostic, would you agree?
>
> I don't know why you're not using a 'for' loop:
>
> /* Circa line 22 */
> size_t i;
>
> for (i = 0; i < Countof(bar_cfg); ++i)
> {
> bc->val = 123 + (unsigned)(bc->name[0]);
> result += bc->val;
> ++bc;
> }
> return result;
> }
>


There is another "problem" here, and that's that you are indexing into
the array with two difference indices. I'd suggest either:

/* Circa line 21 */
size_t i;

for (i = 0; i < Countof(bar_cfg); ++i)
{
bar_cfg[i]->val = 123 + (unsigned)(bar_cfg[i]->name[0]);
result += bar_cfg[i]->val;
}
return result;
}

Or:

/* Circa line 21 */
bar_cfg_t * const end = bar_cfg + Countof(bar_cfg);
bar_cfg_t * bc;

for (bc = bar_cfg; bc < end; ++bc)
{
bc->val = 123 + (unsigned)(bc->name[0]);
result += bc->val;
}
return result;
}

(By the way, I like your spaces surrounding your asterisk in the pointer
declaration. :) )

- Shao Miller

Ben Bacarisse 01-10-2013 02:37 PM

Re: [MUDFLAP] Is sizeof(ARRAY[0]) equivalent to sizeof(*ARRAY) ?
 
m.labanowicz@gmail.com writes:

> Ok, after long investigation I have successfully prepared simple C
> program that illustrates the issue:
> 3 files:
> - bar.h
> - bar.c
> - main.c


A data point: your example compiles and runs clean with gcc 4.7.2 and
mudflap 4.7.

<snip>
--
Ben.

m.labanowicz@gmail.com 01-10-2013 02:48 PM

Re: [MUDFLAP] Is sizeof(ARRAY[0]) equivalent to sizeof(*ARRAY) ?
 
Code without loops, issue is still present:

----------------------------------------------
+ uname -a
Linux ldrlinux 3.2.0-35-generic-pae #55-Ubuntu SMP Wed Dec 5 18:04:39 UTC 2012 i686 i686 i386 GNU/Linux
+ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 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.
+ gawk '{printf("%02u: %s\n", NR, $0);}' bar.h
01: int bar_fun(unsigned idx);
02: #define ARRAY_NO_OF_ELEMENTS(a) ((unsigned)(sizeof(a) / sizeof(*a)))
+ gawk '{printf("%02u: %s\n", NR, $0);}' bar.c
01: #include "bar.h"
02: int bar_fun(unsigned idx)
03: {
04: int bar_cfg [][2] =
05: {
06: {9, 0},
07: {8, 1},
08: {7, 2},
09: {6, 3},
10: {5, 4},
11: {4, 5},
12: {3, 6},
13: {2, 7},
14: #ifdef WORKAROUND_FOR_MUDFLAP
15: {1, 8},
16: #endif
17: {0, 9}
18: };
19: return (idx < ARRAY_NO_OF_ELEMENTS(bar_cfg)) ? bar_cfg[idx][1] : -1;
20: }
+ gawk '{printf("%02u: %s\n", NR, $0);}' main.c
01: #include <stdio.h> /* printf */
02: #include <stdlib.h> /* EXIT_SUCCESS */
03: #include "bar.h"
04: static int foo_fun(unsigned idx)
05: {
06: int const TOSTEP [][2] =
07: {
08: {0, 9},
09: {1, 8},
10: {2, 7},
11: {3, 6},
12: {4, 5},
13: {5, 4},
14: {6, 3},
15: {7, 2},
16: {8, 1},
17: {9, 0}
18: };
19: return (idx < ARRAY_NO_OF_ELEMENTS(TOSTEP)) ? TOSTEP[idx][1] : -1;
20: }
21: int main(void)
22: {
23: printf("Hello World !\r\n");
24: printf("foo_fun = %d\r\n", foo_fun(4));
25: printf("bar_fun = %d\r\n", bar_fun(4));
26: return EXIT_SUCCESS;
27: }
+ gcc -ansi -pedantic -Wall -W -Werror -fmudflap -c bar.c
+ gcc -ansi -pedantic -Wall -W -Werror -fmudflap -c main.c
+ gcc -Wl,-Map,a.map main.o bar.o -lmudflap
+ MUDFLAP_OPTIONS=-mode-check -viol-nop -verbose-trace -internal-checking -print-leaks -check-initialization -verbose-violations
+ ./a.out
+ gawk '{printf("%02u: %s\n", NR, $0);}'
01: *******
02: mudflap violation 1 (register): time=1357829219.568594 ptr=0xbfd9f6b8 size=72
03: pc=0xb762b85e
04: /usr/lib/i386-linux-gnu/libmudflap.so.0(__mf_register+0x3e) [0xb762b85e]
05: ./a.out() [0x8048979]
06: ./a.out() [0x80489e2]
07: Nearby object 1: checked region begins 8B into and ends 79B into
08: mudflap object 0x9a021e8: name=`constant'
09: bounds=[0xbfd9f6b0,0xbfd9f6ff] size=80 area=static check=0r/0w liveness=0
10: alloc time=1357829219.568588 pc=0xb762b85e
11: number of nearby objects: 1
12: mf: alloca stack level 0xbfd9f5a8
13: Hello World !
14: foo_fun = 5
15: bar_fun = 4
16: *******
17: mudflap violation 2 (unregister): time=1357829219.569060 ptr=0x9a02678 size=0
18: pc=0xb762b3d6
19: number of nearby objects: 0
20: number of leaked objects: 0
------------[with: WORKAROUND_FOR_MUDFLAP]--------------------
+ rm -fr bar.o main.o a.map a.out
+ gcc -ansi -pedantic -Wall -W -Werror -fmudflap -DWORKAROUND_FOR_MUDFLAP=1 -c bar.c
+ gcc -ansi -pedantic -Wall -W -Werror -fmudflap -c main.c
+ gcc -Wl,-Map,a.map main.o bar.o -lmudflap
+ MUDFLAP_OPTIONS=-mode-check -viol-nop -verbose-trace -internal-checking -print-leaks -check-initialization -verbose-violations
+ ./a.out
+ gawk '{printf("%02u: %s\n", NR, $0);}'
01: mf: harmless duplicate reg 0xbfbc1c50-0xbfbc1c9f `constant'
02: mf: alloca stack level 0xbfbc1b48
03: Hello World !
04: foo_fun = 5
05: bar_fun = 4
06: number of leaked objects: 0
----------------------------------------------

Usage of sizeof(ARRAY[0]) or sizeof(*ARRAY) has no impact to the result,
issue is present.

Best Regards

--
Maciej Labanowicz


All times are GMT. The time now is 04:40 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.