2009-03-28 9 views
6

Para mi clase de lenguajes de programación, estoy escribiendo un documento de investigación sobre algunos documentos de algunas personas importantes en la historia del diseño del lenguaje. Uno por CAR Hoare me pareció extraño porque habla en contra de las técnicas de compilación independientes utilizadas en C y más tarde en C++ antes de que C incluso se hiciera popular.¿Cómo evitan los lenguajes como C# y Java C/C++, como la compilación independiente?

Dado que esto es principalmente una optimización para acelerar los tiempos de compilación, ¿qué tienen que ver con Java y C# que les permiten evitar la compilación independiente? ¿Es una técnica de compilación o hay elementos del lenguaje que facilitan esto? ¿Y hay otros lenguajes compilados que hayan usado estas técnicas antes que ellos?

Respuesta

5

Respuesta corta: Java y C# no evitan la compilación por separado; hacen uso completo de eso.

Donde difieren es que no requieren que el programador escriba un par de archivos de encabezado/implementación por separado al escribir una biblioteca reutilizable. El usuario escribe la definición de una clase una vez, y el compilador extrae la información equivalente al "encabezado" de esa única definición y la incluye en el archivo de salida como "tipo de metadatos". Por lo tanto, el archivo de salida (un .jar lleno de archivos .class en Java, o un ensamblado .dll en lenguajes basados ​​en .NET) es una combinación de binarios y encabezados en un solo paquete.

Luego, cuando se compila otra clase y depende de la primera clase, puede mirar los metadatos en lugar de tener que encontrar un archivo de inclusión separado.

Ocurre que se dirigen a una máquina virtual en lugar de a una arquitectura de chip específica, pero eso es un problema aparte; podrían poner el código máquina x86 como el binario y aún así tener los metadatos tipo encabezado en el mismo archivo (esta es de hecho una opción en .NET, aunque rara vez se usa).

En los compiladores de C++ es común intentar acelerar la compilación usando "encabezados precompilados". Los metadatos en los archivos .NET .dll y .class se parecen mucho a un encabezado precompilado, ya analizado e indexado, listo para consultas rápidas.

El resultado es que en estos lenguajes modernos, hay una forma de modularización, y tiene las características de un sistema de construcción modular C++ perfectamente organizado y optimizado a mano - bastante ingenioso, hablando ASFAC++B.

4

IMO, uno de los principales factores aquí es que tanto java como .NET utilizan lenguajes intermedios; eso significa que la unidad compilada (jar/assembly) contiene, como prerrequisito, muchos metadatos expresivos sobre los tipos, métodos, etc. lo que significa que ya está dispuesto de manera conveniente para la verificación de referencias. El tiempo de ejecución todavía se comprueba de todos modos, en caso de que esté tirando de uno rápido ;-p

Esto no está muy lejos del MIDL que sustenta COM, aunque allí el TLB a menudo es una entidad separada.

Si he entendido bien su significado, por favor hágamelo saber ...

+0

I * cree * usted me entendió correctamente. Básicamente me refiero a la idea en C/C++ de que cada archivo fuente sea su propia unidad de compilación individual. Esto no parece ser el caso en C# o Java. –

2

Se requiere un poco de apoyo en el idioma (de lo contrario, los compiladores de C/C++ lo harían también)

En particular, se requiere que el compilador genera módulos autónomos, que exponen metadatos a los que otros módulos pueden hacer referencia para llamarlos.

. Los ensamblajes .NET son un ejemplo directo. Todos los archivos de un proyecto se compilan juntos, generando un dll. Dll puede ser consultado por .NET para determinar qué tipos contiene, de modo que otros ensamblados puedan llamar a las funciones definidas en él.

Y para hacer uso de esto, debe ser legal en el lenguaje para hacer referencia a otros módulos.

En C++, ¿qué define el límite de un módulo? El lenguaje especifica que el compilador solo considera los datos en su unidad de compilación actual (archivo .cpp + encabezados incluidos). No hay ningún mecanismo para especificar "Me gustaría llamar a la función Foo en la barra de módulos, aunque no tenga el prototipo ni nada parecido en tiempo de compilación". El único mecanismo que tiene para compartir información de tipo entre archivos es con #includes.

Hay una propuesta para agregar un sistema de módulo a C++, pero no estará en C++ 0x. La última vez que vi, el plan era considerarlo para un TR1 después de que 0x fuera.

(Vale la pena mencionar que el sistema # include en C/C++ fue utilizado originalmente porque había velocidad compilación. En los años 70, permitió que el compilador para procesar el código en un simple escaneo lineal. Se no tenía que crear árboles de sintaxis u otras características "avanzadas". Hoy, las tablas han cambiado y se ha convertido en un gran cuello de botella, tanto en términos de usabilidad como velocidad de compilación).

+0

El diseño de los lenguajes C se basó más en tratar de garantizar que la compilación fuera factible en máquinas con memoria limitada, que en tratar de hacerlo rápido. Hoy en día, hay relativamente pocos sistemas cuyo código fuente completo no encajaría fácilmente en la memoria RAM de una máquina de escritorio típica, pero C se diseñó en una era en la que una máquina grande tendría menos de 1/16,000 de RAM en la actualidad. puesto de trabajo.Los entornos de desarrollo tuvieron que hacer concesiones severas entre la velocidad de compilación y el tamaño de compilación más grande y práctico. – supercat

2

Los archivos objeto generados por una C/C++ deben ser leídos solo por el vinculador, no por el compilador.

1

En cuanto a otros idiomas: IIRC Turbo Pascal tenía "unidades" que podría utilizar sin tener ningún código fuente. Creo que el objetivo es crear metadatos junto con un código compilado que luego pueda ser utilizado por el compilador para descubrir la interfaz del módulo (es decir, firmas de funciones, diseño de clase, etc.).)

Un problema con C/C++ que impide simplemente reemplazar #include con algún tipo de #import es también el preprocesador, que puede cambiar por completo el significado/sintaxis, etc. de los módulos incluidos/importados. Esto sería muy difícil (si no imposible) con un sistema de módulos similar a Java.

3

Podría considerar que un archivo java .class es similar a un archivo de encabezado precompilado en C/C++. Básicamente, el archivo .class es la forma intermedia que necesitaría un enlazador C/C++, así como toda la información contenida en el encabezado (Java simplemente no tiene un encabezado separado).

Forma tu comentario en otro post:.

"Estoy básicamente significa que no la idea en C/C++ que cada fichero fuente es su propia unidad de compilación individuales Esta hace tanto parecen ser el caso en C# o Java. "

En Java (no puedo hablar por C#, pero supongo que es el mismo) cada archivo fuente es su propia unidad de compilación individual. No estoy seguro de por qué pensaría que no es así ... ¿tal vez tenemos diferentes definiciones de unidad de compilación?

Cuestiones relacionadas