Domanda

Sto cercando una bella risposta in stile overflow dello stack alla prima domanda nel vecchio post del blog C ++ codice dimensione , che lo ripeto qui di seguito:

  

Mi piacerebbe molto un certo attrezzo (idealmente, g ++ based) che mi mostra quali parti del codice compilato / collegate sono generati da quali parti del codice sorgente C ++. Per esempio, per vedere se un particolare modello viene creata un'istanza per centinaia di tipi diversi (risolvibili attraverso una specializzazione modello) o se il codice viene inline eccessivamente, o se funzioni particolari sono più grandi del previsto.

È stato utile?

Soluzione

Si fa sembrare qualcosa di simile dovrebbe esistere, ma non ho usato niente di simile. Posso dirvi come mi piacerebbe andare su script questo insieme, però. Probabilmente ci sono più rapidi e / o più sexy modi per farlo.

Prima un po 'di roba che si può già sapere:

Il comando addr2line prende in un indirizzo e può dirvi dove il codice sorgente che il codice macchina lì attrezzi. L'eseguibile deve essere costruita con i simboli di debug, e non sarà probabilmente vuole ottimizzarlo molto (-O0, -O1, o -Os è probabilmente il più in alto che ci si vuole andare in un primo momento comunque). addr2line ha diverse bandiere, e si vorrà leggere la sua pagina di manuale, ma sarà sicuramente bisogno di usare -C o --demangle se volete vedere C ++ nomi delle funzioni che hanno senso in uscita.

Il comando objdump può stampare tutti i tipi di cose interessanti sulla roba in molti tipi di file oggetto. Una delle cose che può fare è stampare una tabella che rappresenta i simboli o di cui da un file oggetto (compresi gli eseguibili).

Ora, che cosa si vuole fare con questo:

Che cosa si vorrà è per objdump di dirvi l'indirizzo e la dimensione della sezione .text. Questo è dove vive attuale codice macchina eseguibile. Ci sono diversi modi per farlo, ma il più semplice (per questo, in ogni caso) è probabilmente da fare per voi:

objdump -h my_exe | grep text

Questo dovrebbe tradursi in qualcosa di simile:

 12  .text       0000049  000000f000  0000000f000 00000400  2**4

Se non è stato grep che darebbe un titolo come:

Idx  Name        Size     VMA         LMA         File off  Algn

Credo che per gli eseguibili VMA e LMA dovrebbe essere lo stesso, in modo da non importa quale si utilizza, ma penso che LMA è il migliore. Si potrà anche le dimensioni.

Con la LMA e la dimensione è possibile chiamare ripetutamente addr2line chiedere per il codice sorgente origine del codice macchina. Non sono sicuro di come questo possa funzionare se avete passato un indirizzo che era all'interno di un insegnamento, ma penso che dovrebbe funzionare.

addr2line -e my_exe <address>

L'uscita da questo sarà un percorso / nome file, due punti e un numero di riga. Se si dovesse contare il verificarsi di ciascun file / percorso unico: num si dovrebbe essere in grado di guardare quelli che hanno i più alti conteggi. Perl hash utilizzando il file / percorso: num come chiave e un contatore come valore sarebbe un modo semplice per implementare questo, anche se ci sono modi più veloci se si scopre che corre troppo lento. Si potrebbe anche filtrare le cose che si possono determinare non hanno bisogno di essere inclusi in anticipo. Per la visualizzazione l'output si consiglia di filtrare le linee differenti dalla stessa funzione, ma si può notare che le linee diverse all'interno di una funzione ha diversi titoli, che potrebbero essere interessanti. In ogni caso, che potrebbe essere fatto sia facendo addr2line vi dico il nome della funzione o utilizzando objdump -t nel primo passo e lavorare una funzione alla volta.

Se vedete che un codice modello o altre linee di codice vengono visualizzati nei tuoi eseguibili più spesso di quanto si pensi che dovrebbe allora si può facilmente localizzarli e dare un'occhiata più da vicino. Le macro e funzioni inline possono mostrare finiscono per manifestarsi in modo diverso da quella prevista.

Se non lo sapeva, e objdump addr2line sono dalla href="https://en.wikipedia.org/wiki/GNU_Binutils" rel="nofollow noreferrer"> GNU binutils pacchetto , che comprende diversi altri strumenti utili.

Altri suggerimenti

Se stai cercando di trovare fonti di pesantezza del codice nel codice C ++, ho usato 'nm' per questo. Il seguente comando elencherà tutti i simboli della tua app con il codice ei dati più grandi pezzi in alto:

nm --demangle --print-size --size-sort --reverse-sort <executable_or_lib_name> | less

ho scritto recentemente uno strumento, gonfiare di colpa , che fa qualcosa di simile a ciò che < a href = "https://stackoverflow.com/questions/2509734/break-down-c-code-size/2510872#2510872"> nategoose proposto .

Non so se sarà d'aiuto, ma non v'è una bandiera gcc di scrivere il codice assembly che genera un file di testo per il vostro esame.

" -S     Usato al posto di -c per causare il file sorgente assembler da generare, utilizzando .s come l'estensione, al posto del file oggetto. Questo può essere utile se è necessario esaminare il codice assembly generato. "

Nella maggior parte dei compilatori C c'è un modo per generare un file MAP. Questo file elenca tutte le librerie compilate il loro indirizzo e la loro dimensione. È possibile utilizzare il file mappa per aiutare a determinare quali file si dovrebbe essere alla ricerca di ottimizzare prima.

Non so come mappare code-> assembly generato in generale.

Per istanze di modello si può usare qualcosa come "stringhe -a | grep | sort -u | GC ++ filt". Per ottenere un quadro approssimativo di ciò che è stato creato

Gli altri due elementi che hai citato sembrano piuttosto soggettivo realtà. Ciò che è "troppo" inlining? Sei preoccupato il file binario è sempre gonfiato? L'unica cosa da fare v'è in realtà andare in gdb e smontare il chiamante per vedere che cosa ha generato, nulla per controllare inline "eccessiva" in generale.

Per dimensioni la funzione, ancora una volta sono curioso perché è importante? Stai cercando di trovare il codice che si espande in modo imprevisto durante la compilazione? Come fai a definire ciò che una dimensione prevista è per uno strumento per esaminare? Anche in questo caso, si può sempre fingere qualsiasi funzione che si sospetta è la compilazione di codice molto più di quanto si vuole, e vedere esattamente ciò che il compilatore sta facendo.

In Visual C ++, questo è essenzialmente ciò che file PDB sono per.

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