JamesLens
JamesLens

Reputation: 457

C ld link-time error with global variables

I'm reading Computer Systems: A Programmer's Perspective, and I came across the following C files:

Foo.c:

void f(void);

int x = 15213;
int y = 15212;

int main()
{
    f();
    printf("x = 0x%x y = 0x%x \n", x, y);
    return 0;
}

Bar.c:

double x;
void f()
{
    x = -0.0;
}

which are compiled with gcc -o foobar foo.c bar.c and gives the following output:

 x = 0x0 y = 0x80000000

Wow. So since int is 4 bytes and double is 8 bytes (on my system anyway) and the strong symbol of x is in Foo.c, x is assigned the hex representation of -0.0, which in turn overwrites y too!

So I'd like to know more about this. How come the standard C type safeguards don't come into play here? Is 0x0000000080000000 blindly written to where x is stored in the ELF, and y happens to be next to it and gets overwritten? Feel free to be as detailed as possible.

Upvotes: 2

Views: 2784

Answers (2)

Gopi
Gopi

Reputation: 19864

You are violating "One definition rule"

An external definition is an external declaration that is also a definition of a function (other than an inline definition) or an object. If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof or _Alignof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one.

which leads to undefined behavior.Basically you have 2 definitions for the object x and declaration also varies.The standard says

All declarations that refer to the same object or function shall have compatible type; otherwise, the behavior is undefined.

Note: %x is used to print out the unsigned int in the unsigned hexadecimal format and trying to print out a negative number using %x leads to undefined behavior.

Using wrong format specifier leads to undefined behavior.

Upvotes: 3

Karthikeyan.R.S
Karthikeyan.R.S

Reputation: 4041

Have you noticed that this warning is coming when you are compiling.

/usr/bin/ld: Warning: alignment 4 of symbol `x' in /tmp/cciNZgVG.o is smaller than 8 in /tmp/cc8pYw6O.o

It is undefined behavior. Don't ignore the warnings. And it producing the answer based on the value you are assigning.

Upvotes: 3

Related Questions