Affidatevi al compilatore per rimuovere il codice inutilizzato o #ifdef?

4

Sto lavorando su uno stack USB in C. Questo stack sarà open source e usato in vari progetti diversi.

Sono disponibili varie opzioni di configurazione che abilitano o disabilitano grandi blocchi di codice e strutture di dati costanti. Poiché si tratta di un progetto incorporato, è importante ridurre al minimo l'ingombro dello stack e uno dei vantaggi della disattivazione delle funzionalità non utilizzate è una riduzione dell'uso di memoria flash e RAM.

Ci sono due modi per rimuovere il codice non utilizzato dall'output del processo di compilazione. L'uso delle direttive del preprocessore #ifdef fa sì che il compilatore non consideri nemmeno il codice inusato. Gli svantaggi principali sono l'inquinamento del codice con un sacco di #ifdefs e il potenziale per rompere il codice disabilitato e non ottenere un avvertimento / errore del compilatore.

L'altra opzione è includere il codice ma consentire al linker di rimuoverlo. GCC è molto bravo in questo, e l'output risultante è della stessa dimensione come se fosse stato rimosso con #ifdef . Il lato negativo di questo è che richiede almeno un livello minimo di ottimizzazione da abilitare ( -O1 , funzioni nelle sezioni e rimozione della sezione inutilizzata) e questo comportamento non è garantito su altri compilatori o su altre versioni di GCC.

Qual è la migliore pratica qui e perché? Quali sono i vantaggi e gli svantaggi che non ho considerato?

    
posta user 16.03.2018 - 11:41
fonte

4 risposte

4

Vai per le direttive del preprocessore. Non dovrebbero inquinare troppo il codice (se lo fanno, puoi probabilmente refactoring quelle sezioni ed estrarle in una funzione separata, possibilmente inline, aumentando la sua manutenibilità).

Secondo me, il punto più importante è che non puoi sapere se questa sezione di codice sarà effettivamente utilizzata o meno. Gli IDE moderni di oggi possono evidenziare o attenuare quelle sezioni a seconda della configurazione che stai creando, quando si trova all'interno di un blocco #if ... # endif. Ciò rende il codice più gestibile e facile da identificare. Affidarsi esclusivamente al compilatore / ottimizzatore lo renderà chiaro solo a se stesso, senza alcun vantaggio pratico in termini di efficienza, prestazioni o dimensioni del programma.

    
risposta data 16.03.2018 - 12:52
fonte
2

L'ottimizzazione rimuovendo il codice inutilizzato è una delle più vecchie ottimizzazioni disponibili. Ricorda che i computer utilizzavano meno risorse. Molte delle piattaforme embedded odierne dispongono di più risorse rispetto ai desktop 30 anni fa. Se la tua toolchain incorporata non rimuove il codice non utilizzato, è francamente un pezzo di spazzatura.

#ifdefs sono difficili da leggere e difficili da mantenere. Non continuerai a tenere il passo così come praticamente nessun compilatore scritto negli ultimi 40 anni che non sia un progetto di classe undergrad.

    
risposta data 16.03.2018 - 17:56
fonte
2

Credo che la risposta corretta a " #ifdef o ottimizzazione linker" sia .

Vorrei usare #ifdef attorno a parti grandi e importanti che potrebbero non essere utilizzate (ad esempio, codice specifico del supporto USB 3.0) per consentire allo sviluppatore di eseguire una "sgrossatura" dell'oggetto finale, quindi lasciare che il linker esegue l'ottimizzazione finale.

Questo ha il vantaggio di dare un po 'di controllo allo sviluppatore per l'ottimizzazione dello spazio del codice su larga scala mentre non richiede loro di usare l'ottimizzazione ad alto livello nella fase di linker se non lo desiderano (ricorda, ad alta l'ottimizzazione del livello può rifattorizzare il codice così tanto che quando si esegue lo stepping singolo in un debugger ciò che sta facendo il codice assembly / machine ha una scarsa somiglianza con il codice C così come è scritto).

    
risposta data 20.03.2018 - 19:19
fonte
-1

"This stack will be open source"

è in conflitto con

"this behaviour isn't guaranteed on other compilers, or even other versions of GCC."

Se altre persone costruiscono il codice sorgente non puoi fare affidamento su di loro usando il compilatore approvato.

Supponiamo che io usi il tuo progetto ma per qualche ragione devo usare un compilatore che non ottimizzi il codice così bene.

Sarò costretto a pubblicare il tuo progetto, aggiungere le dichiarazioni #ifdef e pubblicarlo come "USBStackProject_ForOldCompilers" o qualcosa del genere.

Se stavi distribuendo i binari non penso che sarebbe importante come li hai prodotti. Ma dovresti rendere il codice che distribuisci il lavoro con tutti i compilatori che è ragionevole.

    
risposta data 16.03.2018 - 13:18
fonte

Leggi altre domande sui tag