Cómo se compila un binario, de código a proceso

Publicado el 2026-09-12 por frfrand

Las cuatro etapas que convierten texto en un programa, qué hace el enlazador y por qué falla tanto, la diferencia entre enlazado estático y dinámico, y qué pasa al ejecutarlo.

Cómo se compila un binario, de código a proceso

Escribís código, corrés un comando, aparece un ejecutable. En el medio hay cuatro etapas, y saber cuál es cuál cambia por completo la interpretación de los errores.

1. Preprocesado

Se resuelven las directivas: se pegan los archivos incluidos, se expanden las macros, se eliminan los bloques condicionales que no aplican.

El resultado sigue siendo texto, normalmente mucho más largo que el original.

2. Compilación

El compilador traduce ese texto a instrucciones de máquina. Verifica la sintaxis, aplica optimizaciones y genera un archivo objeto por cada archivo fuente.

Un archivo objeto tiene código máquina, pero no es ejecutable todavía: contiene referencias a cosas que están en otro lado. Si tu código llama a una función definida en otro archivo, el objeto guarda el nombre y un espacio a completar.

Los errores de esta etapa son los familiares: un punto y coma, un tipo que no coincide, una variable no declarada. Te dicen archivo y línea.

3. Enlazado

Acá es donde aparecen los errores que más desconciertan.

El enlazador junta todos los objetos y las bibliotecas, y resuelve cada referencia pendiente: para cada nombre usado, busca dónde está definido y anota la dirección.

Si un nombre no aparece en ningún lado, falla con el clásico:

undefined reference to 'mi_funcion'

Este error confunde porque parece un error de compilación y no lo es. El compilador estuvo perfectamente feliz: sabía que esa función existía en algún lado. El que no la encuentra es el enlazador.

Las causas habituales: falta agregar un archivo a la compilación, falta enlazar una biblioteca (el clásico -lm para matemáticas), o el orden de las bibliotecas está mal (el enlazador las procesa en orden y algunos casos son sensibles a eso).

Estático o dinámico

Una decisión con consecuencias muy prácticas.

Enlazado estático: el código de las bibliotecas se copia adentro de tu ejecutable. El binario es más grande y no depende de nada externo: lo copiás a otra máquina y funciona.

Enlazado dinámico: el ejecutable guarda sólo el nombre de la biblioteca, y se carga al ejecutar. El binario es chico, y varios programas comparten la misma biblioteca en memoria. Además, una actualización de seguridad de la biblioteca beneficia a todos los programas sin recompilar.

El costo del dinámico es el error del otro extremo:

error while loading shared libraries: libfoo.so.3: cannot open shared object file

Eso es tiempo de ejecución: el programa compiló y enlazó bien, pero al arrancar no encuentra la biblioteca. Para ver de qué depende un binario:

ldd /usr/bin/miprograma

Este es el motivo por el que un binario compilado en una distribución puede no correr en otra, y es también una de las razones por las que existen los contenedores: encapsular el conjunto exacto de bibliotecas.

4. Cargar y ejecutar

Cuando ejecutás el programa, el kernel lee la cabecera del archivo (en Linux, formato ELF), reserva memoria, mapea las secciones de código y datos, y le pasa el control al cargador dinámico, que resuelve las bibliotecas que faltan y finalmente salta al punto de entrada.

Curiosidad: el segmento de código se mapea en modo sólo lectura y compartido. Si ejecutás el mismo programa veinte veces, el código está una sola vez en memoria física.

Y los lenguajes que no compilan así

Python, JavaScript o Ruby no producen un binario nativo. Se interpretan, o se compilan a un formato intermedio que ejecuta una máquina virtual.

Java y C# están en el medio: compilan a bytecode y lo traducen a código nativo mientras corren.

Go y Rust hacen lo contrario y por eso se hicieron populares en infraestructura: producen un binario estático que no depende de nada. Copiás el archivo al servidor y anda. Sin intérprete, sin bibliotecas del sistema, sin entorno virtual.

  • compilación
  • binarios
  • linker
  • Linux
  • fundamentos

Seguir leyendo

Todos los artículos · Planes de VPS