ho avuto un problema strano che ho ridotto al seguente test case:Accesso globali statiche in una funzione inline
inl.h:
inline const char *fn() { return id; }
a.cc:
#include <stdio.h>
static const char *id = "This is A";
#include "inl.h"
void A()
{
printf("In A we get: %s\n", fn());
}
b.cc:
#include <stdio.h>
static const char *id = "This is B";
#include "inl.h"
void B()
{
printf("In B we get: %s\n", fn());
}
extern void A();
int main()
{
A();
B();
return 0;
}
Ora quando compilo questo con g++ -O1 a.cc b.cc
sembra funzionare correttamente. Ottengo:
In A we get: This is A
In B we get: This is B
ma se compilo con g++ -O0 a.cc b.cc
ottengo:
In A we get: This is A
In B we get: This is A
Nota che sto effettivamente cercando di utilizzare la semantica C11 qui, ma sto usando g ++ come gcc non lo fa supporto C11 ancora.
Ora, per quanto posso vedere, guardando sia le specifiche C11 sia le specifiche C++ (C++ 11 e le specifiche precedenti - la semantica di globalità in linea e statica non sembra essere cambiata), dovrebbe fare quello che voglio, e l'errore quando si utilizza -O0
è un bug in gcc.
È questo corretto, o c'è qualcosa da qualche parte nelle specifiche che mi manca che renderebbe questo comportamento indefinito?
Modifica
La risposta comune sembra sostenere che fn
deve essere dichiarato come static
per questo lavoro. Ma secondo 6.7.4.6 delle specifiche C99 (6.7.4.7 nella specifica C11 - non sono sicuro delle specifiche C++):
Se tutte le dichiarazioni di ambito di file per una funzione in un'unità di traduzione includono funzione inline specificatore senza extern, quindi la definizione in quell'unità di traduzione è una definizione in linea . Una definizione in linea non fornisce una definizione esterna per la funzione, e non vieta una definizione esterna in un'altra unità di traduzione.
Quindi, poiché non c'è un esplicito extern
qui, queste dovrebbero essere due funzioni inline indipendenti senza interazione l'una con l'altra. Non è richiesto esplicito static
.
L'utilizzo di uno statico esplicito risolve il problema per C, ma non funziona per le funzioni membro inline C++, poiché la parola chiave static
ha un significato completamente diverso in quel caso.
Fuori interesse, il comportamento viene replicato se si sostituisce l'include con la definizione della funzione in linea? Se il preprocessore funziona come un primo passaggio indipendente come immagino, dovresti essere in grado di semplificare il test case. –
Btw: quale versione di gcc? –
gcc 4.5.3 e 4.6.1 si comportano entrambi in questo modo. –