Domanda

Cerchiamo di incorporare una cosa stringa all'interno di oggetti binari in modo che possiamo vedere il numero di versione per una libreria eseguibile o condivisa che è stato distribuito. In genere noi incorporiamo informazioni standard CVS Id in questo ciò che stringa. Ad esempio, potremmo incorporare:

const char cvsid[] = "@(#)OUR_TEAM_staging_remap_$Revision: 1.30 $ $Name:  $";

all'interno del codice C.

Da uomo (1) cosa:

  

La cosa utility cerca ogni nome di file per le occorrenze di   il modello @ (#) che il CSSC comando get (vedi CSSC-get (1))   sostituti per l'ID parola chiave @ (#), e le stampe quanto segue   fino ad una",>, NEWLINE, \, o il carattere NULL.

C'è una sola istanza di questa variabile e non è mai indicato. Qualcuno ha suggerito che questo potrebbe avere ottimizzato via dal compilatore.

Ho usato questa tecnica per molti anni sia in C e C ++ e con una varietà di compilatori e non ho ancora vedere una cosa stringa ottimizzato via.

Qualcuno ha un'idea perché non sono ottimizzati via?

È stato utile?

Soluzione

Fino a poco (ho notato il problema a metà del 2005), è stato possibile utilizzare:

static const char sccs[] = "@(#)%W% %E%";

o qualcosa di simile nel codice sorgente e GCC e la maggior parte degli altri compilatori non sarebbe ottimizzarlo via. A partire dalla versione di GCC da circa quel tempo (probabilmente 4.0.x GCC, provenienti da aprile 2005), quelle stringhe costanti sono stati lasciati fuori dai binari. Così, ho dovuto andare in giro modificare il mio codice sorgente per rendere le variabili visibili esternamente. Non è possibile per il compilatore a guardare il file oggetto solo e concludere che la stringa è inutilizzata perché qualcosa al di fuori del file potrebbe plausibilmente riferimento a esso. Così, i miei file ora contengono:

#ifndef lint
extern const char jlss_id_filename_c[];
const char jlss_id_filename_c[] = "@(#)$Id$";
#endif /* lint */

OK - che è un ibrido; Ho davvero usare RCS per memorizzare il codice sorgente, ma io continuo a preferire what per ident per l'identificazione dei file - più ho la mia violato <=> che fa entrambe le <=> e <=> più un paio di modifiche della mia proprio. Ma ho la dichiarazione in alcuni file - non tutti - e la definizione di tutti i file. (Sotto un insieme di segnali di avvertimento, non ora ricordato, mi è stato sempre avvisi quando la variabile è stata definita prima di essere dichiarato Potrebbe essere stato un cambiamento nel GCC che ha risolto il problema,.. Non sono sicuro di più)

Quando creo un nuovo file, il mio generatore modello sostituisce il 'filename_c' con il nome appropriato del file generato. Allo stesso modo per le intestazioni -. Anche se la stringa di identificazione è incorporato in un solo file per evitare molteplici definizioni

ho preferito il vecchio sistema con costanti statiche - ma questo ha lavorato per me per oltre 3 anni

.

Altri suggerimenti

In genere questo non accade perché le stringhe estranei hanno poco costo e può essere utile in casi come questo, tra gli altri (per esempio la memorizzazione di un gruppo di risorse di stringa con solo il primo in realtà si fa riferimento nel codice).

Non possono essere ottimizzate via perché il compilatore sa che tali stringhe possono essere utilizzati per questi scopi.

Naturalmente, il compilatore è completamente permesso di ottimizzare la via, fino a quando il comportamento del programma, più esattamente il comportamento osservabile, non è cambiato. Ciò significa che la sequenza di scrive e legge di volatili, e le chiamate a funzioni di libreria non viene modificato.

Con l'ottimizzazione di un tale stringa nella vostra applicazione via, suppongo che il comportamento non cambierà. Ma compilatori vogliono essere utilizzabile e cercare di non colpire nel modo gli utenti. È per questo che contengono estensioni utili troppo. Se si vuole essere sicuri che non è ottimizzato via in alcune occasioni, però, forse a dare un'occhiata nelle estensioni compilatori. GCC ha una unused attributo, che lo rende non emette gli avvisi per gli oggetti inutilizzati. Forse questo o qualcosa di simile può aiutare la variabile non è ottimizzato via.

Da un punto di vista di lingua, là isn 'un programma di utilità anche se per forzare il compilatore di tenerlo.

Modifica : C'è stato un post su questo argomento usenet qui , con le risposte utili.

di Microsoft Visual C ++ 2005 ha un opzione del linker che dovrebbe controllare che cosa fa con i dati non utilizzati:. /OPT:UNREF costringe il linker per mantenere i dati non utilizzati, /OPT:REF permette di eliminarlo

Tuttavia, a mio semplice test, l'opzione ha avuto alcun effetto sul conto economico

static char VersionString[] = "HELLO_WORLD 2.0";

La stringa è apparso in entrambi i binari di rilascio e di debug, indipendentemente dalla bandiera.

Senza la "statica" parola chiave variabile non può essere ottimizzata via, perché un altro modulo può dichiarare un riferimento ot (usando esterno). Dal momento che C / C ++ è di solito compilato un file alla volta, non c'è modo il compilatore può sapere se esiste un riferimento esterno.

Con l'aggiunta della parola chiave static dirvi il compilatore che il nome è visibile solo all'interno della compilation utilizzando e ottimizzando via diventa possibile.

Credo che il linker potrebbe rilevare una variabile globale non utilizzato e ottimizzarlo via anche se il formato oggetto lo permette, anche se non sono sicuro che chiunque fa.

(Sì, so che questo è stato chiesto e ha risposto tempo fa. Ma questo nuovo stile di risposta è disponibile, in modo ....)

In gcc (almeno in 3.3 e seguenti), v'è ora la direttiva del compilatore __attribute__((unused)) per segnalare una variabile come "noto che potrebbe non può essere fatto riferimento" per sopprimere avvertimenti, e __attribute__((used)) a bandiera come usato (e quindi non è un candidato per essere ottimizzato out), anche se nessun altro codice fa riferimento in realtà.

Quindi questo potrebbe fare per voi:

static const char what_ident[] __attribute__((used)) = "@(#) $Id$";

Se il linker ancora ottimizza fuori, quindi potrebbe essere necessario per metterla in una sezione che è contrassegnato come mantenere indipendentemente riferimenti temporali di collegamento.

static const char what_ident[] __attribute__((section("what"), used)) = "@(#) $Id$";

e aggiungere l'opzione gcc -Wl,-bkeepfile:file.o in modo che il linker non sopprimere le sezioni non si fa riferimento nella produzione di file.c.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top