2011-07-15 11 views
8

tengo el siguiente código fuente en main.cpp:g ++ funciona, pero no "g ++ -c" y ld

#include <iostream> 
#include <iomanip> 

int main() { 
    std::cout << "Hi" << std::endl; 
    return 0; 
} 

Usando este comando funciona, y crea el archivo ejecutable:

g++ -o main main.cpp 

Pero esta comandos no funcionan:

g++ -c main.cpp 
ld -o main main.o 

El segundo uno con errores:

ld: warning: cannot find entry symbol _start; defaulting to 00000000004000e8 
main.o: In function `main': 
main.cpp:(.text+0xa): undefined reference to `std::cout' 
main.cpp:(.text+0xf): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)' 
main.cpp:(.text+0x14): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)' 
main.cpp:(.text+0x1c): undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))' 
main.o: In function `__static_initialization_and_destruction_0(int, int)': 
main.cpp:(.text+0x4a): undefined reference to `std::ios_base::Init::Init()' 
main.cpp:(.text+0x4f): undefined reference to `std::ios_base::Init::~Init()' 
main.cpp:(.text+0x54): undefined reference to `__dso_handle' 
main.cpp:(.text+0x61): undefined reference to `__cxa_atexit' 
+2

ld no sabe acerca de libstdC++ –

+0

No llame a ld directamente, a menos que realmente lo necesite. –

Respuesta

13

Creo que si usa ld directamente, no incluye las bibliotecas C++ de forma predeterminada. Puede usar g++ para hacer los enlaces, llamará al ld con la configuración correcta.

g++ -c main.cpp 
g++ -o main main.o 
7

Cuando se utiliza g++, también vincula la biblioteca libstd++ cuales enlazador utiliza para resolver los nombres. Pero usando g++ -c y luego ld no vincule la biblioteca automáticamente. Tienes que vincular la biblioteca manualmente ahora.

Try (no probado):

ld -o main main.o -llibstd++ 

O se puede mirar en la sintaxis correcta mediante la lectura de este manual:

+0

el indicador para vincular con la biblioteca libstdC++ es -lstdC++ – hailinzeng

1

Bueno, no vinculó en la biblioteca estándar. g++ hace esto automáticamente; es por eso que lo usamos: envuelve las llamadas a ccplus1 y ld con todos los extras atendidos.

Por cierto, en sentido estricto, el equivalente de g++ main.cpp -o main es:

cc1plus main.cpp -o main.o 
ld -o main main.o 

(cc1plus así no puede estar en su camino, me encontré mina en /usr/libexec/gcc/i386-redhat-linux/4.1.1/)

g++ -c main.cpp hace tradicionalmente realizan esa primera paso. g++ main.cpp -o main envuelve ambos.

g++ es un contenedor a las herramientas individuales de compilación y enlace, sintonizadas para C++. Como tal, proporciona argumentos a cc1plus y ld como lo considere oportuno, incluyendo el argumento para vincular en el ++ biblioteca estándar de C:

ld -o main main.o -llibstd++ 

También enlazaremos en el tiempo de ejecución y, posiblemente, algunas otras cosas.

En general, no hay necesidad de intentar hacer estas cosas usted mismo: deje que g++ se ocupe de ello.

12

GCC enlaces internos contra algunas bibliotecas adicionales y archivos de objetos.Para ver cuáles son, ejecute -###, que imprimirá los comandos de la herramienta que ejecutará, incluido el vinculador. El comando del enlazador utilizado por mi GCC es (hice el archivo .o real que invoqué g++ en en negrita, por lo que puede detectarlo fácilmente).

/usr/lib/gcc/i686-pc-linux-gnu/4.6.0/collect2 --build-id --eh-frame-HDR -m elf_i386 "estilo --hash = ambos" -dynamic-linker /lib/ld-linux.so.2 /usr/lib/gcc/i686-pc-linux-gnu/4.6.0/../../../crt1.o/usr/lib/gcc/i686-pc-linux-gnu/4.6.0 /../../../ crti.o /usr/lib/gcc/i686-pc-linux-gnu/4.6.0/crtbegin.o -L /usr/lib/gcc/i686-pc-linux-gnu/4.6.0 -L/usr/lib/gcc/i686-pc-linux-gnu/4.6.0 /../../ .. main1. o "-lstdC++" -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/i686-pc-linux-gnu/4.6.0/crtend.o/usr/lib/gcc/i686-pc -linux-gnu/4.6.0 /../../../ crtn.o

Puede sustituir el collect2 ruta por ld (si mal no recuerdo, collect2 solo es necesario como un proxy para los back-ends GCC que no son compatibles con los formatos binarios modernos, recoge constructor y las funciones de destructor según su nombre destruido. El formato ELF tiene soporte de secciones nativas para eso).

Ejecutando ese comando, con ld sustituido literalmente, vincula exitosamente el ejecutable.