mersenneforum.org

mersenneforum.org (https://www.mersenneforum.org/index.php)
-   Programming (https://www.mersenneforum.org/forumdisplay.php?f=29)
-   -   gcc 10.2.0 behavior (https://www.mersenneforum.org/showthread.php?t=26291)

bsquared 2020-12-08 21:47

gcc 10.2.0 behavior
 
A couple times now I have seen reports where gcc 10.2.0 failed to compile a project that older gcc versions (and icc) compiled just fine. They fail with errors in the linking stage; complaining about multiple definitions of global constants defined in headers (e.g., see [URL="https://www.mersenneforum.org/showpost.php?p=565667&postcount=79"]here[/URL]).

I know that global definitions in headers is poor form, but it will be a pain to fix if that is the only solution going forward. The headers are all protected from being included twice using the usual #ifndef X #define X macros, which have worked up until now.

Any thoughts on fixes, or ideas about what happened with this newer gcc version?

Nick 2020-12-08 22:00

I tend to program defensively and avoid C's concept of "tentative definitions".
If a variable declaration initializes the variable then the compiler must regard it as a definition.
If a variable declaration says "extern" instead then the compiler must view it as merely a declaration
(or have they changed the rules again?)

bsquared 2020-12-08 23:04

[QUOTE=Nick;565708]I tend to program defensively and avoid C's concept of "tentative definitions".
If a variable declaration initializes the variable then the compiler must regard it as a definition.
If a variable declaration says "extern" instead then the compiler must view it as merely a declaration
(or have they changed the rules again?)[/QUOTE]

I would think that has remained the same, but I don't keep up to date on these things.

For clarity, here is an example of what I'm talking about.

header1.h:
[CODE]
#ifndef HEADER1_H
#define HEADER1_H

/* defines */

/* typedefs */

/* function declarations */

/* globals */
int foo;
int bar;

#endif
[/CODE]

Now, if two source files, say main.c and worker.c both #include header1.h, only one set of the globals should be defined. At least, that is how it has worked up to gcc 10.2.0.

If I have to update everything using externs to declare the globals and then define them once (probably in main.c), then so be it, but if there is a cheaper, hackier way to do what I want (compile the program as-is) then I'd like to at least consider it.

mathwiz 2020-12-09 01:48

Possibly helpful? [url]https://gcc.gnu.org/gcc-10/porting_to.html[/url]

"A common mistake in C is omitting extern when declaring a global variable in a header file. If the header is included by several files it results in multiple definitions of the same variable. In previous GCC versions this error is ignored. GCC 10 defaults to -fno-common, which means a linker error will now be reported. To fix this, use extern in header files when declaring global variables, and ensure each global is defined in exactly one C file."

bsquared 2020-12-09 03:33

[QUOTE=mathwiz;565725]Possibly helpful? [url]https://gcc.gnu.org/gcc-10/porting_to.html[/url]

"A common mistake in C is omitting extern when declaring a global variable in a header file. If the header is included by several files it results in multiple definitions of the same variable. In previous GCC versions this error is ignored. GCC 10 defaults to -fno-common, which means a linker error will now be reported. To fix this, use extern in header files when declaring global variables, and ensure each global is defined in exactly one C file."[/QUOTE]

Yeah, I'd say that explains it exactly. Looks like I have some work to do... in the meantime hopefully building with an earlier version of gcc is a workaround.

VBCurtis 2020-12-09 05:26

If there's a flag that "defaults to -fno-common", can't we (well, you) just set that flag the opposite way at compile time?

mathwiz 2020-12-09 12:20

[QUOTE=VBCurtis;565747]If there's a flag that "defaults to -fno-common", can't we (well, you) just set that flag the opposite way at compile time?[/QUOTE]

Perhaps, but it seems like sticking in the extern's is the more syntactically correct approach, and should work with all gcc versions without the need to fiddle with compiler flags...

EdH 2021-01-17 16:38

[QUOTE=VBCurtis;565747]If there's a flag that "defaults to -fno-common", can't we (well, you) just set that flag the opposite way at compile time?[/QUOTE]The page referenced earlier does suggest:
[QUOTE=Porting to GCC 10] As a workaround, legacy C code where all tentative definitions should be placed into a common block can be compiled with -fcommon.[/QUOTE]I have tried using this flag in a variety of places within the YAFU Makefile, with no success.

[QUOTE=mathwiz;565756]Perhaps, but it seems like sticking in the extern's is the more syntactically correct approach, and should work with all gcc versions without the need to fiddle with compiler flags...[/QUOTE]The error file from a compile attempt resulted in 3876 "multiple definitions." This represents a substantial amount of work to resolve by editing to include "extern."

I am looking at a project to write a script to do all this editing based on the list of multiple definitions. But, my concern is that all the first instances of each definition did not flag the error. Should all those instances also include "extern," or, is a single point that doesn't, have to exist? If the latter, is there a correct place for the initial definition, such as the main code block?

EdH 2021-01-17 17:57

In some small playing, this appears beyond my capabilities and apparently not within my understanding, either. I tried to use extern for a couple of the "multiple definitions," but there are no second instances of declaration. If I "extern" the one reference, I get "undefined references." If I add a definition to the offended file, it does appear to fix that one issue, but I have no understanding of Ben's intricacies of the YAFU code and the editing is not scriptable from my point of view. Although not fully abandoned, I do not expect to play with this very much more, at least for now.

ldesnogu 2021-01-17 18:27

A trick is to play with #define extern.

bsquared 2021-01-17 18:50

I am actively working on this.


All times are UTC. The time now is 04:28.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.