int bar = 2;
if (bar)
{
int bar;
}
Neither gcc or Clang manages to issue a warning (or error) for this, and the program crashes immediately on launch. Is there a good reason for this? It doesn't seem like it would be something hard to catch. It's the basics of block scoping: the nested scope inherits the names of the enclosing block...
Any explanations?
EDIT: It turns out the crash was due to using Clang. I've tested many times back and forth, and it seems certain that the combination of the variable redefinition and Clang causes the crash. However, I haven't been able to reproduce the crash in a test project, so go figure.
The problem turned out to be Objective-C related. As Jonathan Leffler points out doing ´int bar = bar´ in the inner scope initializes the variable from itself, and that's what causes the problem, when the initialization is done via an Objective-C method call.
The following shows the bug in action:
-(void)crasher
{
NSNumber* bar = [NSNumber numberWithInt:2];
if (bar)
{
NSString* bar = [self doit:bar];
}
}
-(NSString*)doit:(NSNumber*)num
{
NSString* str = [num stringValue]; // This line causes the crash
return str;
}
Note that doing something similar in pure C does not produce a crash:
int bar = 2;
if (bar)
{
char buff[10];
int bar = sprintf(buff, "%d",bar);
}
Extending the answer given by Douglas Leeder:
#include <stdio.h>
static int xx(int foo)
{
int bar = 2;
if (foo > bar)
{
int foo = bar;
int bar = bar;
printf("inner: foo = %d, bar = %d\n", foo, bar);
}
printf("outer: foo = %d, bar = %d\n", foo, bar);
return bar;
}
int main(void)
{
xx(13);
return(0);
}
Note that the inner bar is initialized from itself - which gives undefined behaviour. But on MacOS X 10.6.2 (GCC 4.2.1) I get:
inner: foo = 2, bar = 0
outer: foo = 13, bar = 2
Interestingly, I get the same output from this code, with a stack trampling function, regardless of whether I declare i
before or after a
.
inner: foo = 2, bar = 20
outer: foo = 13, bar = 2
Code:
#include <stdio.h>
static void modify_stack(void)
{
int a[20];
int i;
for (i = 0; i < 20; i++)
{
a[i] = 0xFFFFFFFF ^ i;
printf("a[i] = 0x%08X\n", a[i]);
}
}
static int xx(int foo)
{
int bar = 2;
if (foo > bar)
{
int foo = bar;
int bar = bar;
printf("inner: foo = %d, bar = %d\n", foo, bar);
}
printf("outer: foo = %d, bar = %d\n", foo, bar);
return bar;
}
int main(void)
{
modify_stack();
xx(13);
return(0);
}
Since the behaviour is undefined, this result is fine.
#include <stdio.h>
static int modify_stack(void)
{
int a[20];
int i;
for (i = 0; i < 20; i++)
{
a[i] = 0xFFFFFFFF ^ i;
printf("a[i] = 0x%08X\n", a[i]);
}
i = a[13];
return(i);
}
static int xx(int foo)
{
int bar = 2;
if (foo > bar)
{
int foo = bar;
int bar = bar;
printf("inner: foo = %d, bar = %d\n", foo, bar);
}
printf("outer: foo = %d, bar = %d\n", foo, bar);
return bar;
}
int main(void)
{
int i = modify_stack();
xx(13);
return(i & 0xFF);
}
Output (apart from data printed in loop):
inner: foo = 2, bar = -14
outer: foo = 13, bar = 2