Why no compilation error.

S

sunny

We have three files a.c, b.c and main.c respectively as follows:
a.c
---
int a;
b.c
---
int a = 10;
main.c
------
extern int a;
int main()
{
printf("a = %d\n",a);
return 0;
}
Let's see what happens, when the files are compiled together:
bash$ gcc a.c b.c main.c
bash$ ./a.out
a = 10
Hmm!! no compilation/linker error!!! Why is it so??
 
J

Jack Klein

We have three files a.c, b.c and main.c respectively as follows:
a.c
---
int a;
b.c
---
int a = 10;
main.c
------
extern int a;
int main()
{
printf("a = %d\n",a);
return 0;
}
Let's see what happens, when the files are compiled together:
bash$ gcc a.c b.c main.c
bash$ ./a.out
a = 10
Hmm!! no compilation/linker error!!! Why is it so??

Your program produces undefined behavior by having more than one
definition of an external object. The compiler is free to do anything
it wants. Once you generate undefined behavior, the C language no
longer places any requirements on the results.
 
P

Peter Nilsson

Note: gcc has not been invoked as a conforming compiler, so you
can't have any expectations under the C language standard.
Your program produces undefined behavior by having more than one
definition of an external object. The compiler is free to do anything
it wants. Once you generate undefined behavior, the C language no
longer places any requirements on the results.

Or, to more accurately answer the OP's question, the behaviour is UB
by 6.9p5, however that paragraph is not one of the listed Contraints
for 6.9 [pp2-3], so no diagnostic is required.

Why it's not a constraint, I don't know.
 
G

Guest

Peter said:
Note: gcc has not been invoked as a conforming compiler, so you
can't have any expectations under the C language standard.
Your program produces undefined behavior by having more than one
definition of an external object. The compiler is free to do anything
it wants. Once you generate undefined behavior, the C language no
longer places any requirements on the results.

Or, to more accurately answer the OP's question, the behaviour is UB
by 6.9p5, however that paragraph is not one of the listed Contraints
for 6.9 [pp2-3], so no diagnostic is required.

Why it's not a constraint, I don't know.

I imagine it's not a constraint because depending on the system, it may
not have an easy way to tell this apart from a definition whose name
matches that of a library function provided as an extension. In other
words, it could also generate a diagnostic for this legitimate code:

#include <stdio.h>
void write(char *s) { puts(s); }
int main(void) {
write("Hello, world!");
}
 
S

sunny

Hi All
but i get the compilation error if i initialize the variable "a" in a.c
ie.
// in a.c
int a = 200;

// in b.c
int a = 10.

on compilation, now i got multiple definition error.
may on first i.e uninitialized "a" will be stored in BSS section and
intialized "a" (a = 10) is stored in DS(data segment). so when i
intialize "a" in a.c
it will move to DS where it confilicts with "a" from b.c;

is it correct?

Peter said:
Note: gcc has not been invoked as a conforming compiler, so you
can't have any expectations under the C language standard.
Your program produces undefined behavior by having more than one
definition of an external object. The compiler is free to do anything
it wants. Once you generate undefined behavior, the C language no
longer places any requirements on the results.

Or, to more accurately answer the OP's question, the behaviour is UB
by 6.9p5, however that paragraph is not one of the listed Contraints
for 6.9 [pp2-3], so no diagnostic is required.

Why it's not a constraint, I don't know.
 
J

Jack Klein

Hi All
but i get the compilation error if i initialize the variable "a" in a.c
ie.
// in a.c
int a = 200;

// in b.c
int a = 10.

on compilation, now i got multiple definition error.
may on first i.e uninitialized "a" will be stored in BSS section and
intialized "a" (a = 10) is stored in DS(data segment). so when i
intialize "a" in a.c
it will move to DS where it confilicts with "a" from b.c;

is it correct?

It is not correct. It is not incorrect. Once you produce undefined
behavior, the C standard no longer specifies what the program must do.
As far as the C language is concerned, anything that happens is just
as correct or incorrect as anything else.

You have broken a rule of C programming. Don't do that. Then you
won't have to worry whether what happens is correct.
 
J

Jean-Marc Bourguet

sunny said:
We have three files a.c, b.c and main.c respectively as follows:
a.c
---
int a;
b.c
---
int a = 10;
main.c
------
extern int a;
int main()
{
printf("a = %d\n",a);
return 0;
}
Let's see what happens, when the files are compiled together:
bash$ gcc a.c b.c main.c
bash$ ./a.out
a = 10
Hmm!! no compilation/linker error!!! Why is it so??

With gnu linker, use -Wl,--warn-common. That's the (sloppy) common unix
practice.

A+
 
A

Amigo

The variable is defined / initialised in two separate files. Each of
these C files will be compiled to object code. At the linking phase,
the linker usually has a specific order in which it searches for
external symbols, e.g. start with all the objects/libraries in current
folder in alphabetical order, followed by the so-called default paths
where other libraries and objects may reside. All the linkers I've
used, by default, will stop looking for an external reference if one
has already been found in an object or a library. Therefore, in this
case, it so happened that the linker encountered the definition with
initialisation first, hence the value 10 is displayed at execution. I
suppose a closer investigation of the linker properties would provide a
clear answer to this issue. Changing the initialisation from one file
to the other may exhibit a different behaviour (or at least I expect
to).

Romeo Ghiriti
 
A

Amigo

The variable is defined / initialised in two separate files. Each of
these C files will be compiled to object code. At the linking phase,
the linker usually has a specific order in which it searches for
external symbols, e.g. start with all the objects/libraries in current
folder in alphabetical order, followed by the so-called default paths
where other libraries and objects may reside. All the linkers I've
used, by default, will stop looking for an external reference if one
has already been found in an object or a library. Therefore, in this
case, it so happened that the linker encountered the definition with
initialisation first, hence the value 10 is displayed at execution. I
suppose a closer investigation of the linker properties would provide a
clear answer to this issue. Changing the initialisation from one file
to the other may exhibit a different behaviour (or at least I expect
to).

Romeo Ghiriti
 
J

Jean-Marc Bourguet

Amigo said:
The variable is defined / initialised in two separate files. Each of
these C files will be compiled to object code. At the linking phase,
the linker usually has a specific order in which it searches for
external symbols, e.g. start with all the objects/libraries in current
folder in alphabetical order, followed by the so-called default paths
where other libraries and objects may reside. All the linkers I've
used, by default, will stop looking for an external reference if one
has already been found in an object or a library. Therefore, in this
case, it so happened that the linker encountered the definition with
initialisation first, hence the value 10 is displayed at execution. I
suppose a closer investigation of the linker properties would provide a
clear answer to this issue. Changing the initialisation from one file
to the other may exhibit a different behaviour (or at least I expect
to).

I think you are confusing two issues. A linker will not import an object
file if it doesn't provides some undefined symbol. (That's one way for
providing extensions in a library and still beeing able to use those
symbols in user programs; another way -- which is mandatory for dynamic
library which can't be broken into parts -- is to use something like elf's
weak symbols).

When the linker has decided that an object must be part of the image (and
all linkers I know consider that all object files directly given on the
command line are in that class), the linkers give error message for
duplicate definitions. Unix linker traditionnaly don't give such error
message when all but one of the definitions are tentative definitions.

Yours,
 
D

Default User

Christopher said:
Default User said:
Please don't top-post.

Wouldn't the [TPA] be better placed at the beginning of the post title
rather than the end?

Why? Where do I put it, before the "Re:"? Just after? I'm flexible, but
the end made more sense and is slightly easier to do, as it's easy it
position the cursor at the end accurately.

It's there so that people who want to filter can. The filter probably
doesn't care where it is.





Brian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top