2014-09-17 31 views
14

Sono un principiante C++ e sto studiando le basi della lingua. C'è un argomento nel mio libro sul compilatore e il mio problema è che non riesco a capire ciò che il testo vuole dire:Differenza tra oggetto codice e file eseguibile

C++ è un linguaggio compilato quindi è necessario tradurre il codice sorgente in un file che il computer può essere eseguito. Questo file è generato dal compilatore ed è chiamato il codice oggetto (obj), ma un programma come il programma "ciao mondo" è composto da una parte che abbiamo scritto e una parte della libreria C++. Il linker collega queste due parti di un programma e produce un file eseguibile (.exe).

Perché il mio libro dico che il file che viene eseguito dal computer è quella con il obj suffisso (il codice oggetto) e poi dire che è quello con la exe ​​ suffisso?

+3

I file di origine dei vostri programmi sono compilati in file oggetto, e quindi il linker collega quelli oggetto file insieme, producendo un file eseguibile. – 0x499602D2

+1

Per andare con l'analogia del tuo libro, 'printf (" Ciao, mondo! \ N ");' è la parte che "scriviamo" così il codice oggetto potrebbe avere istruzioni per chiamare 'printf' per esempio. La libreria standard è la parte che effettivamente implementa 'printf' (come sta andando a stampare ??). Questa è la differenza. Ovviamente tipicamente in C++ scriviamo "cout <<" Hello, world! \ N ";' come primo programma ma l'idea è la stessa. – Brandin

risposta

27

I file oggetto sono compilati in linguaggio macchina binario, ma contengono riferimenti esterni non risolti (ad esempio printf, ad esempio). Potrebbe essere necessario collegarsi ad altri file di oggetti, librerie di terze parti e quasi sempre contro la libreria di runtime C/C++.

In Unix, sia gli oggetti che i file exe hanno lo stesso formato COFF. L'unica differenza è che i file oggetto hanno riferimenti esterni non risolti, mentre i file a.out no.

+9

No, COFF è obsoleto nella maggior parte degli Unix. Usano (come Linux) ELF! –

+3

Vero, grazie. Abbreviazione diversa, stessa differenza nel contesto della domanda! – ArunasR

8

La specifica C++ è un documento tecnico in inglese. Per C++11 dare un'occhiata all'interno di n3337 (o spendere un sacco di soldi per acquistare lo standard ISO tascabile). In teoria non hai bisogno di un computer per eseguire un programma C++ (potresti usare un sacco di schiavi umani, ma non sarebbe etico, inefficiente e inaffidabile).

Si potrebbe avere un applicazione C++ che è un interpreter, non un compiler (ad es Ch by SoftIntegration)

Se si installa Linux su un computer portatile (che vi consiglio di fare a tutti gli studenti), allora si potrebbe avere diversi free software compilatori C++ , in particolare GCC e Clang/LLVM (utilizzando rispettivamente i comandi g++ e clang). I file di origine sono suffritti .cc o .cxx o .cpp o .C oppure preferisco .cc e si può chiedere al compilatore di gestire un file di qualche altro suffisso come file sorgente C++ (ma non è convenzionale). Quindi, sia object files (suffisso .o) che executables condividono lo stesso formato ELF. Convenzionalmente, eseguibili non hanno alcun suffisso (ad esempio g++ è un binario eseguibile, non sta facendo molto, tranne a partire altri processi come cc1plus -il prietà compilatore, as -la assembler -, ld -la linker - ecc ...)

In tutti i casi vi consiglio vivamente:

  • per consentire a tutti gli avvertimenti e le informazioni di debug durante la compilazione (ad esempio l'uso g++ -Wall -g ....)
  • per migliorare il codice sorgente fino a che non ho ricevuto avvertimenti
  • per imparare a utilizzare il debugger (gdb)
  • per essere in grado di costruire il programma da riga di comando
  • ad utilizzare un sistema di controllo versione come git
  • di utilizzare un buon editor come emacs, gedit, geany, o gvim
  • una volta si sta scrivendo programmi in diversi file sorgente, imparare a usare un costruttore come make
  • imparare il C++ 11 (o forse anche C++14) piuttosto che vecchie norme
  • C++ per imparare anche altri linguaggi di programmazione (OCaml, Scheme, Haskell, Prolog, Scala, ....), in quanto migliorerebbero il tuo modo di pensare e codificare in C++
  • per studiare il codice sorgente di diversi software liberi codificati in C++
  • per leggere la documentazione di ogni funzione che stai usando, ad es. su cppreference o in man pages (per Linux)
  • per capire cosa è undefined behavior (il fatto che a volte il tuo programma funzioni non lo rende corretto).

Concretamente, su Linux è possibile modificare il vostro programma Ciao Mondo (file hello.cc) con gedit o emacs (con un comando come gedit hello.cc) ecc ..., compilarlo usando g++ -Wall -g hello.cc -o hello di comando, eseguire il debug utilizzando gdb ./hello, e ripetere (non dimenticare di usare i comandi git per il controllo della versione).

A volte ha senso generare un codice C++, ad es. da qualche shell, Python, o awk script (o anche dal proprio programma codificato in C++ che genera codice C++!).

Inoltre, si capisce che uno è non un un compilatore (ma esegue il compilatore per te).

+0

Clang è particolarmente bravo a segnalare avvisi ed errori e sicuramente meglio a farlo rispetto a GCC. Supporta anche i nuovi standard più rapidamente. Raccomando l'OP di usarlo, poiché sarà meno di un ostacolo. – Kalrish

+0

Non esattamente vero: il recente GCC 4.9 ha migliorato molto per quanto riguarda gli avvertimenti e supporta C++ 11 –

+0

Anche se GCC è migliorato, la sua diagnostica non è ancora chiara e non supporta C++ 14 (mentre Clang, come di 3.5, fa). La qualità del codice generato (macchina) è una storia diversa, tuttavia :). – Kalrish

3

Le lingue utilizzate per la programmazione dei computer insieme ai vari strumenti di sviluppo del software si sono evolute nel corso degli anni.

I primi computer sono stati programmati con i numeri immessi dagli interruttori su una console.

Quindi le persone hanno iniziato a sviluppare linguaggi e software che potrebbero essere utilizzati per creare software più facilmente e più rapidamente. Il primo grande sviluppo fu la creazione del linguaggio assemblatore in cui ogni linea di origine veniva convertita da un programma per computer in un'istruzione di codice macchina. Insieme a questo è venuto lo sviluppo di linker (che collegano pezzi di codice macchina insieme in pezzi più grandi). Gli assemblatori sono stati migliorati aggiungendo una macro o una funzione di preprocessore in qualche modo simile al preprocessore C/C++, sebbene progettata per il linguaggio assembly.

Quindi le persone hanno creato linguaggi di programmazione che somigliavano più a persone che scrivevano lingue piuttosto che a assemblatori (FORTRAN e COBOL e ALGOL per esempio). Queste lingue erano più facili da leggere e una singola riga di origine poteva essere convertita in diverse istruzioni macchina, quindi era più produttivo scrivere programmi per computer in queste lingue piuttosto che assemblatore.

Il linguaggio di programmazione C è stato un ulteriore perfezionamento utilizzando le lezioni apprese dai primi linguaggi di programmazione come FORTRAN. E C ha utilizzato alcuni degli stessi strumenti di sviluppo software già esistenti come i linker che esistevano già. Ancora più tardi è stato inventato il C++, che inizia come un perfezionamento di C che introduce strutture orientate agli oggetti. In effetti, il primo compilatore C++ era davvero un traduttore C++ che traduceva il codice sorgente C++ in codice sorgente C che veniva poi compilato con un compilatore C. Tuttavia, il C++ moderno è compilato direttamente su codice macchina per fornire tutte le funzionalità dello standard C++ con modelli, lambda e tutte le altre cose con C++ 11 e versioni successive.

I passaggi di base per la creazione di un'applicazione da un file sorgente C o C++ sono i seguenti: (1) vengono creati i file di origine, (2) i file di origine sono compilati (in realtà due passaggi, Preprocessore e compilazione), (3) i file oggetto creati dal compilatore C/C++ sono collegati per creare l'exe

Così hai questi passaggi per trasformare una versione del programma per computer in un'altra. Il sorgente C++ è compilato per produrre i file oggetto. I file oggetto vengono quindi collegati per produrre il file eseguibile.

Quando si esegue un programma si esegue il file eseguibile. Il file eseguibile contiene diversi tipi di informazioni. Il primo è le istruzioni della macchina che sono il risultato della compilazione del codice sorgente C++. L'altro è informazioni che il caricatore utilizza per sapere come caricare l'eseguibile in memoria.

In passato, molto tempo fa tutte le librerie e i file oggetto erano collegati insieme in un file eseguibile e il file eseguibile veniva caricato dal caricatore e il caricatore era piuttosto semplice.

Quindi le persone hanno inventato librerie condivise e librerie di collegamenti dinamici e ciò ha richiesto che il caricatore fosse più complesso. Non solo il caricatore deve caricare il file eseguibile in memoria in modo che possa iniziare a funzionare, il caricatore deve anche trovare librerie condivise o librerie di collegamenti dinamici che sono anche necessarie e caricare anche quelle. E il caricatore deve anche fare una certa quantità di collegamento dei componenti aggiuntivi, le librerie condivise, quindi il caricatore fa molto più di quanto non fosse abituato a fare.

+0

Questa è un'ottima risposta, vorrei inoltre raccomandare il libro "Linkers and Loaders" di John R. Levine. –

2

Codice oggetto (all'interno di un file oggetto): uscita da un compilatore inteso come input per un linker (affinché il linker produca codice eseguibile).

eseguibile: un programma pronto per essere eseguito (eseguito) su un computer

Problemi correlati