This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
volatile is not volatile enough
- From: Jan Engelhardt <jengelh at linux01 dot gwdg dot de>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Wed, 25 Jun 2003 15:20:57 +0200 (MEST)
- Subject: volatile is not volatile enough
- Reply-to: Hirogen2 <hirogen2 at gmx dot de>
Hi,
given a statement like
int a[2];
func2(func1(a), a[0], a[1]);
where a is modified by func1, func2 receives wrong input on the stack. In
detail, first a[1], then a[0] and then a is pushed onto the stack, then func1
gets called and pops off its a -- which is modified after.
Adding the keyword volatile doesnot help.
I am using gcc 3.3 20030226 (prerelease) SuSE Linux 8.2.
Here is a test script:
#include <stdio.h>
#define volatile
volatile void *func1(volatile int[]);
volatile void *func2(volatile void *, volatile int, volatile int);
int main(void) {
volatile int a[2] = {13, 101};
volatile void *result;
/* IMPACT
The result on stdout should be x=14 y=102 not x=13 y=101.
*/
func2(func1(a), a[0], a[1]);
/* CAUSE
Unknown, however, when using objdump:
8048344: 55 push %ebp
8048345: 89 e5 mov %esp,%ebp
8048347: 83 ec 18 sub $0x18,%esp
804834a: 83 e4 f0 and $0xfffffff0,%esp
804834d: b8 00 00 00 00 mov $0x0,%eax
8048352: 29 c4 sub %eax,%esp
8048354: c7 45 f8 0d 00 00 00 movl $0xd,0xfffffff8(%ebp)
804835b: c7 45 fc 65 00 00 00 movl $0x65,0xfffffffc(%ebp)
8048362: 83 ec 04 sub $0x4,%esp
Here it comes, GCC uses a "trick" to save instructions:
it already pushes a[0] and a[1] onto the stack, and then a itself,
while func1 only pops its one argument, a -- which gets modified.
Even if adding the volatile keyword, this behavior does not change.
Even if adding it everywhere.
8048365: 8b 45 fc mov 0xfffffffc(%ebp),%eax
8048368: 50 push %eax
8048369: 8b 45 f8 mov 0xfffffff8(%ebp),%eax
804836c: 50 push %eax
804836d: 8d 45 f8 lea 0xfffffff8(%ebp),%eax
8048370: 50 push %eax
8048371: e8 3c 00 00 00 call 80483b2 <func1>
8048376: 83 c4 04 add $0x4,%esp
8048379: 50 push %eax
804837a: e8 59 00 00 00 call 80483d8 <func2>
804837f: 83 c4 10 add $0x10,%esp
*/
// Following works...
result = func1(a);
func2(result, a[0], a[1]);
return 0;
}
volatile void *func1(volatile int a[]) {
++a[0];
++a[1];
return NULL;
}
volatile void *func2(volatile void *p, volatile int x, volatile int y) {
printf("x=%d, y=%d\n", x, y);
return p;
}
EOF
- Jan Engelhardt