2010-10-15 31 views
12

Esta pregunta me ha estado molestando desde hace un tiempo. Vamos a considerar los dos siguientes programas:¿Qué requiere un programa C++ para ejecutarse?

#incude <iostream> 
int main() 
{ 
    std::cout << "Hello, World!"; 
} 

y

int main() 
{ 
    int x = 5; 
    int y = x*x; 
} 
  1. de Windows: El primer ejemplo, naturalmente, requiere un poco de sistema .dll para la consola. Entiendo que. ¿Qué hay del segundo? ¿Necesita algo para ejecutar? Algunas bibliotecas de tiempo de ejecución? Por cierto, ¿qué hacen realmente las bibliotecas de tiempo de ejecución?
  2. Linux: No tengo idea, ¿me puedes aclarar?

Sé que depende del compilador y del sistema operativo, pero necesito una respuesta general o ejemplos particulares. TIA.

+2

toda la suerte en el mundo! – Chubsdad

+0

@Chubsdad true: D –

+1

Su segundo ejemplo no necesita ningún procesamiento, más allá de eso causado por un 'return 0;' from 'main()'. No llama a funciones de ningún tipo, y no tiene acceso a variables 'volátiles ', por lo que no tiene un comportamiento observable. –

Respuesta

1

Los programas C en Windows requieren bibliotecas CRT que vienen con Windows. C++ a veces requiere el llamado "C++ redistribuible". Se pueden integrar en la aplicación a través de enlaces, pero esto hará que EXE sea más grande.

+0

CRT se puede vincular estáticamente con el programa – Abyx

+0

@Andrey. ¿Es la opción en Visual Studio la que dice biblioteca de tiempo de ejecución y puedes configurarla en MT MD MTd, etc.? –

+0

@Andrey.Y también, si especifica en qué casos el programa requiere redistribución de C++, aceptaré su respuesta –

7

Como respuesta general, la primera requerirá las bibliotecas de tiempo de ejecución de C++ (lo que necesita para admitir las llamadas de biblioteca estándar). Estos forman una interfaz de tipo entre el idioma y el bibliotecas de soporte, que a su vez saben cómo lograr lo que hacen en el entorno dado.

El segundo no hace uso de las bibliotecas de tiempo de ejecución. Utilizará el código de inicio y terminación de C (que inicializa y deshace el entorno de C) pero es un punto de discusión sobre si se consideran o no parte de las bibliotecas de tiempo de ejecución. Si los considera parte, entonces, sí, serán utilizados. Probablemente será una pieza muy pequeña utilizada, ya que generalmente hay una gran diferencia de tamaño entre el código de inicio y las novedades.

Puede vincular su código de forma estática (vinculante en tiempo de enlace) con bibliotecas de tiempo de ejecución o dinámicamente (de modo que la vinculación real se realice en tiempo de carga). Eso es cierto tanto para Windows como para Linux.

+1

-1 para "El segundo no hace uso de las bibliotecas de tiempo de ejecución". En general, depende de la biblioteca de tiempo de ejecución para el inicio y la terminación del proceso. En Windows, el runtime lib proporciona el punto de entrada del programa y luego de 'main' llama' ExitProcess' (si recuerdo el nombre correctamente). –

+2

@Alf, ¿no vio el siguiente texto: '" que no sea el código de inicio de C ... "'? También puede ser una cuestión de definición. El código de inicio y finalización _may_ puede estar en el CRT, pero he visto muchas situaciones en las que se trata de un 'start.o' independiente y no tiene nada que ver con la biblioteca estándar. Lo aclararé – paxdiablo

+1

De hecho, es discutible si el código de inicio/término se puede considerar parte de la RTL. Físicamente, está vinculado, así que sí. Pero, lógicamente, no expone los recursos o datos invocables orientados a la aplicación, por lo que no es así. Dado que la respuesta claramente explica esto, -1 definitivamente no tiene sentido. – Stabledog

2

El primer programa realiza la transmisión de E/S, lo que significa que tiene que interactuar con los recursos (consola, interfaz gráfica de usuario) administrados por el sistema operativo. Entonces, en última instancia, el sistema operativo debe invocarse a través de una API implementada en un dll del sistema.

En Windows, el segundo programa no requiere bibliotecas. Estoy bastante seguro de que lo mismo es cierto en Linux.

7

Para las aplicaciones de Windows, puede usar Dependency Walker para ver todas las dependencias.

+1

http://www.dependencywalker.com/ - algo así como un salvavidas cuando se trata de verificar dependencias. –

+1

El equivalente de Linux sería 'ldd': un comando que enumera las bibliotecas de las que depende (y dónde las encuentra). También hay 'nm' para obtener la lista de símbolos a los que se hace referencia, los marcados con' U' (indefinido) son los que irá a buscar en otra DLL. –

1

Para la primera parte de su pregunta, varios miembros le han respondido. Pero lo que digo es general y obligatorio en ambos casos (en caso de que no lo sepa)

Para que se ejecute cualquier programa, debe proporcionarse con los recursos que necesita. Al responder al equipo de la primera parte ya ha enumerado varios elementos.

Pero, en general, lo que necesita es espacio de direcciones bien definido (en la memoria principal), sus propiedades y el tiempo de CPU. El sistema operativo lo garantiza al ejecutar su programa. A menos que exista algún conflicto ridículo, su programa obtendrá eso (y es por eso que creo que Chubsdad comentó "usted necesita suerte").

Programación del sistema operativo, la CPU solicita que se obtengan las instrucciones/datos de la memoria y luego la ejecución ... todo forma una "máquina" que ejecuta su programa.

Encontrar el punto de entrada (o primer punto en su programa para ejecutar) es todo lo que se decide en tiempo de compilación (función principal por ejemplo) o mientras carga su programa usando alguna llamada al sistema como exec() (en Unix)/CreateProcess() (en windows).

2

ellos compilar con GCC, y obtener ejecutable llamado 'hola', en la escritura de la consola:

ldd hi 

le dará los objetos compartidos (bibliotecas dinámicas) que están conectados a su programa.

Sólo para respuesta rápida aquí es una salida:

ldd tifftest 
    libtiff.so.3 => /usr/lib/libtiff.so.3 (0x4001d000) 
    libc.so.6 => /lib/libc.so.6 (0x40060000) 
    libjpeg.so.62 => /usr/lib/libjpeg.so.62 (0x40155000) 
    libz.so.1 => /usr/lib/libz.so.1 (0x40174000) 
    /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) 
+0

Me pregunto por qué usa libjpeg.so – hiena

+1

@hiena: Dado que el programa es "tifftest", sospecho que es un programa de prueba para formatos de imagen. –

+1

Rara vez. En mi caja, los programas C++ siempre son del agrado de linux-gate, libstdC++, libm, libgcc_s, libc y ld-linux. A los programas C solo les gustan linux-gate, libc y ld-linux. No libtiff, libjpeg o libz, a menos que se solicite explícitamente. –

1

En Linux, cualquier programa de C está vinculado estáticamente a algunas bibliotecas CRT. El verdadero punto de entrada del programa es la función _start() definida en /usr/lib/crt1.o. Esta función llama a algunas funciones de libc como __libc_start_main(). Por lo tanto, todavía necesita la biblioteca libc ...

Podría hacer sin libc, pero es complicado. Debería cambiar el nombre de su punto de entrada _start(), o indicar al vinculador que comience en main(). Y también necesitaría un ensamblado en línea para emitir la llamada al sistema _exit() cuando el programa finalice, de lo contrario, simplemente se bloqueará. Y, por supuesto, haga el enlace explícitamente con el comando ld en lugar de a través del frontend gcc.

2

Bueno, vamos a ver esto desde un punto de vista más general:

  • Para empezar, se necesita un ordenador con una CPU compatible que trabaja con equipo de destino de la salida del compilador . Puede pensar que esto es obvio, pero suponiendo que el código se compila en código máquina x86, no se ejecutará en una CPU Alpha que utilice instrucciones diferentes. Alternativamente, si compila a código de máquina x64, no se ejecutará en una CPU de solo x86. Entonces, el hardware correcto es necesario para ejecutar el programa C++, a diferencia de los lenguajes basados ​​en máquinas virtuales como Java, que lo abstraen.

  • También necesitará el sistema operativo correcto. No soy un experto en portar programas, pero no creo que sea posible construir un solo ejecutable que se ejecute en múltiples sistemas operativos en C++. Por ejemplo, compilar incluso su segundo ejemplo en Windows tendrá mucho código de biblioteca de tiempo de ejecución detrás de escena antes y después de la llamada real a su función main(). Esto hará cosas como preparar el montón e inicializar la biblioteca CRT. El CRT para Windows se implementa a través de la API de Windows. Puede enlazar estáticamente la biblioteca para que no se requiera ninguna DLL CRT, pero el código en su programa aún realiza llamadas a la API de Windows, por lo que sigue dependiendo de la plataforma. Como experimento compilé un programa vacío con enlaces estáticos en Windows con Visual Studio, y de acuerdo con Dependency Walker todavía hace referencia a KERNEL32.DLL para funciones como HeapCreate y ExitProcess. Por lo tanto, el programa "vacío" todavía le ofrece un montón de material del sistema operativo, en preparación para hacer algo útil (independientemente de si su programa hace algo útil).

Nótese también es muy posible que una versión mínima del sistema operativo: Visual Studio 2010 requiere Windows XP SP2 o superior, incluso para un programa vacío, debido a las llamadas realizadas a EncodePointer y DecodePointer. Ver this question.

  • El sistema tendrá que tener la memoria disponibles para poner en marcha su programa. Puede pensar que no hace nada, pero como se demostró anteriormente, antes de que main() se llame una carga completa de OS, las llamadas de inicialización las realiza la biblioteca de su programa. Probablemente requieran algo de memoria y el tiempo de procesamiento necesario para ejecutarla.

  • Dependiendo de la configuración del sistema operativo, es posible que necesite suficientes privilegios de seguridad para ejecutar programas ejecutables.

Así que, en definitiva, para ejecutar un programa C++ vacío incluso con la vinculación estática, es necesario que la CPU correcta, el sistema operativo, el permiso para ejecutar el ejecutable, y el tiempo de memoria/procesamiento para completar el programa. En comparación con las tecnologías de VM como Java o .NET, los requisitos se reducirían probablemente a la máquina virtual correcta, los privilegios necesarios y el tiempo necesario de memoria/CPU para ejecutar el programa. Esto puede no ser tan simple como parece: es posible que necesite la versión correcta de una máquina virtual, como .NET framework 4.0. Esto puede complicar su proceso de distribución ya que la actualización de todo el JVM o .NET Framework para una máquina puede ser un proceso lento que requiere privilegios de administrador y tal vez una conexión a Internet. En algunos casos, esto podría ser un factor decisivo, ya que en raras ocasiones puede ser más fácil poder decir "se ejecutará en cualquier sistema operativo Windows compatible con x86 desde XP" en comparación con "cualquier máquina con la última versión virtual". máquina que solo se lanzó ayer ". Sin embargo, para la mayoría de los propósitos, el hecho de que la máquina virtual le permita (en teoría) olvidarse de la CPU y del sistema operativo facilita la distribución del programa; con C++, debe compilar, al menos, ejecutables por separado para cada combinación de plataforma y CPU que desee, independientemente de los requisitos adicionales de las bibliotecas que está utilizando.

Cuestiones relacionadas