Enlazador
Es un programa que toma los objetos generados en los primeros pasos del proceso de compilación, la información de todos los recursos necesarios (biblioteca), quita aquellos recursos que no necesita, y enlaza el código objeto con su(s) biblioteca(s) con lo que finalmente produce un fichero ejecutable o una biblioteca. En el caso de los programas enlazados dinámicamente, el enlace entre el programa ejecutable y las bibliotecas se realiza en tiempo de carga o ejecución del programa.
De igual modo se puede decir que también es un módulo que junta los ficheros de código objetos(generados en la primer parte de la compilación), la información de todos los recursos necesarios (biblioteca), elimina los recursos que no se necesitan y enlaza el código objeto con sus bibliotecas. Finalmente produce el fichero ejecutable o una biblioteca.
Existen programas que se enlazan dinámicamente, esto significa que este proceso se hace en el momento que se carga el programa.
Tiempo de Ejecución:
Se denomina tiempo de ejecución al intervalo de tiempo en el que un programa de computadora se ejecuta en un sistema operativo. Este tiempo se inicia con la puesta en memoria principal del programa, por lo que el sistema operativo comienza a ejecutar sus instrucciones. El intervalo finaliza en el momento en que éste envía al sistema operativo la señal de terminación, sea ésta una terminación normal, en que el programa tuvo la posibilidad de concluir sus instrucciones satisfactoriamente, o una terminación anormal, en el que el programa produjo algún error y el sistema debió forzar su finalización.
Este término suele emplearse, en oposición a tiempo de compilación, para indicar si una acción o hecho sucede en uno u otro tiempo.
Biblioteca Informática
En ciencias de la computación, una biblioteca (del inglés library) es un conjunto de subprogramas utilizados para desarrollar software. Las bibliotecas contienen código y datos, que proporcionan servicios a programas independientes, es decir, pasan a formar parte de estos. Esto permite que el código y los datos se compartan y puedan modificarse de forma modular. Algunos programas ejecutables pueden ser a la vez programas independientes y bibliotecas, pero la mayoría de estas no son ejecutables. Ejecutables y bibliotecas hacen referencias (llamadas enlaces) entre sí a través de un proceso conocido como enlace, que por lo general es realizado por un software denominado enlazador.
La mayoría de los sistemas operativos modernos proporcionan bibliotecas que implementan los servicios del sistema. De esta manera, estos servicios se han convertido en una "materia prima" que cualquier aplicación moderna espera que el sistema operativo ofrezca. Como tal, la mayor parte del código utilizado por las aplicaciones modernas se ofrece en estas bibliotecas.
El GM ENLAZADOR:
Que es:
Son aquellos utilizaran su poder para aumentar tu articulo con LAPICES repetidos o donde no deben estar . Si tienes un articulo con huecos , será enlazado con 2 lápices iguales o en lugares donde no deben y lo mejor: 100% de probabilidad de éxito!.
¿Cómo conseguimos un GM ENLAZADOR?
Se consigue mediante AeriaPoints, Ya NO aparecer en eventos ocasionales, es decir, no es un articulo permanente en el Almacén del artículos AP. Estos eventos solian estar en escalas de premios, ruleta de premios, otros.
¿Cómo hacer para enlazar el artículo que queremos? :
1) Este "GM Enlazador" bajo ningún concepto debíamos sacarlo del banco, así que NO LO QUITES DEL BANCO.
2) Ahora que ya tenemos el artículo en el banco debemos proceder al siguiente paso. Nos dirigimos a la bodega npc, donde guardamos:
La pieza de armadura, arma o accesorio que querían que se enlazarla.
El lápiz que quieras para enlazar la pieza de armadura, arma o accesorio que queremos.
¿Cuántos tipos de enlazadores existen?
• GM Enlazador accesorios
• GM Enlazador Normal.
• GM Enlazador Premium.
• #GM Enlazador Premium Super# .
¿Cuantos enlaces son por GM enlazador?
Cada GM Enlazador vale solamente un enlace.
¿Podía utilizar un GM Enlazase normal para enlazar elementales lvl2 ?
Si, ya no se puede, cada GM Enlazador normal tenia un valor específico.
Así que ya no puedes utilizar un GM Enlazador normal para que te hagan lo quieras.
¿Podía enlazar cualquier artículo con el GM Enlazador normal?
Si, el nivel de conocimiento sobre los artículos que deseas enlazar, es irrelevante, solo necesita ser mas listo que los demás.
Enlazadores referentes a la Programacion:
Enlazado: Este es el concepto detrás de toda la programación: que una máquina adecuada de computación en general puede emular los más específicos. Un programa de ordenador no es más que un medio de convertir un motor de computación de uso general en uno de propósito especial.
Sinopsis:
El proceso de crear un ejecutable comienza por la compilación de varias unidades de compilación independientes. Los ficheros objeto resultantes, junto con librerías ya existentes y algún trozo de código añadido, son después agrupados de forma ordenada en un solo fichero que constituye el ejecutable.
Este proceso de agrupación y ordenación es realizado por un programa especial, el enlazador ("Linker"), cuyo nombre evoca una de sus principales funciones, el enlazado ("Binding"). Este proceso es responsable de que, en el ejecutable, cada instancia de un identificador sea asociada correctamente con una función u objeto particular. A efectos prácticos esto significa que la mayoría de los identificadores utilizados por el programador desaparecen y son sustituidos por direcciones concretas de memoria donde se encuentran los objetos referenciados.
Destacar que el enlazado es un proceso independiente del lenguaje de programación utilizado. Es decir, no es específico de C++. Para obtener un ejecutable, el linker puede partir de una serie de objetos que se han obtenido de la compilación de distintos fuentes, incluso escritos originalmente en lenguajes distintos. La única condición exigida es que tales ficheros-objeto, producidos por un compilador o por un macro-ensamblador, sean del formato adecuado.
De forma sinóptica el proceso responde al siguiente esquema:
En el código fuente:
...
func1(); // invocación de una función
...
El compilador traslada la sentencia anterior a una instrucción del siguiente aspecto:
call func1
El enlazador sustituye el nemónico func1 por una dirección concreta, donde comienza el código correspondiente a la función. Algo parecido a:
call 0x4000000
Sin embargo, aunque la función primordial del enlazador es resolver todas las referencias que puedan existir en el programa y agrupar todos los módulos en un solo fichero, que pueda ser cargado y ejecutado por el Sistema Operativo, realiza además otras funciones. Por ejemplo, insertar en el fichero resultante el código del módulo inicial, que es el encargado de iniciar la ejecución.
Nota: En el caso concreto de Borland C++ el "Linker" es el programa ILINK32.EXE. Pero es bastante raro que sea ejecutado explícitamente durante el proceso de construcción de un ejecutable. Lo normal es que sea invocado indirectamente, a través del programa supervisor. En concreto, el compilador BCC32.EXE invoca al enlazador incluso cuando no hay nada que compilar. Por ejemplo, el comando:
BCC32 mainfile.obj sub1.obj mylib.lib.
Conduce al enlazado de los ficheros MAINFILE.OBJ, SUB1.OBJ y MYLIB.LIB para producir el ejecutable MAINFILE.EXE. Para ello, no solo invoca al enlazador, con los argumentos adecuados, también incluye por su cuenta el módulo de inicio C0W32.OBJ; la librería CW32.LIB y la librería de importación IMPORT32.LIB. Además, le pasa la opción /c (distinguir mayúsculas y minúsculas).
Por su parte, el enlazador GNU es el programa ld.exe (suponemos la versión MinGW para Windows) y para la construcción de proyectos C++, generalmente suele ser invocado por el compilador (g++.exe). Por ejemplo, para enlazar los ficheros del ejemplo anterior en un solo ejecutable main.exe, se utilizaría el siguiente comando:
g++ mainfile.o sub1.o mylib.lib -o "main.exe"
Propiedades del enlazado:
Respecto al enlazado existen dos aspectos a tener en cuenta: uno de ellos tiene que ver con una especie de "ámbito" de nombres dentro del ejecutable. El otro se refiere a "cómo" se enlaza un identificador con el objeto al que representa.
Tipos de Enlazados:
a) Enlazado Estático:
Empezaremos por la segunda de las consideraciones: Hemos dicho que durante el enlazado, el "Linker" asocia cada identificador con el objeto correspondiente. Lo que equivale a decir que asocia el identificador con la dirección del objeto. Esto puede efectuarse en tiempo de compilación o en runtime. Cuando esto puede quedar completamente definido en tiempo de compilación, se dice que se trata de un enlazado previo o estático ("Earlybinding"). Así pues, enlazado estático significa que cuando, por ejemplo, el compilador genera una llamada a una función determinada, el enlazador puede resolverla mediante la dirección absoluta del código que debe ejecutarse. En el caso del esquema anterior , el enlazador pudo determinar que func1comienza en la dirección 0x4000000. Puede ser el caso de una función sobrecargada en la que el compilador puede saber que instancia corresponde a una invocación por el análisis de los argumentos utilizados.
Para la resolución antes descrita, cada vez que el enlazador encuentra el identificador de una variable o de una función, debe buscar en la unidad de compilación que esté utilizando y en caso de no encontrarlo en ella, en el resto de módulos .obj; en los ficheros de recursos .res, y en las librerías .lib que hemos ordenado enlazar juntos. Si finalmente la variable, función o recurso no aparece, el enlazador lanza un mensaje de error: unresolvedexternalreference...
A efectos prácticos, lo anterior supone que código responsable de la funcionalidad del programa, se encuentran en el propio ejecutable, lo que presenta la ventaja de que la aplicación no depende de la existencia de módulos exteriores. Sin embargo, esto es rarísimo en la programación actual. Sobre todo porque en los entorno multiusuario, las aplicaciones no pueden controlar directamente los dispositivos del Sistema, sino que debe hacerlo mediante llamadas a determinados servicios situados fuera del ejecutable (lo contrario, además de ser imposible, exigiría que cada ejecutable englobara gran parte del propio SO).
b) Enlazado Dinámico:
En ocasiones las cosas no suceden como se han descrito en el párrafo anterior. Hay veces en que hasta el momento de la ejecución, el programa no puede (o no quiere) determinar la dirección de la función que se invoca. Esta situación se presenta típicamente cuando se usan las denominadas librerías dinámicas y en la POO, cuando se programan operaciones genéricas con objetos sin saber que objeto concreto (instancia de la clase) la utilizará en su momento. Es decir, se utilizan clases polimórficas.
Para comprender el proceso, supongamos una variación del esquema anterior, en el que la función invocada no se encuentra en un módulo objeto, sino en una librería dinámica (DLL) que solo será cargada en el momento de la ejecución del programa o incluso más tarde; no cuando este arranca, sino cuando se realiza la invocación a la función. En estas condiciones, el enlazador no puede conocer la dirección de func1. La solución adoptada es precisamente el enlazado o dinámico ("Late binding").
En este tipo de enlazado, parte del código necesitado por la aplicación se encuentra en ficheros distintos del propio ejecutable. Por ejemplo, en las conocidas librerías .DLL. El inconveniente es que la ejecución exige la presencia de todos los módulos externos (que pueden estar efectivamente presentes o no). La ventaja es que determinadas habilidades, sobre todo las del propio Sistema Operativo, y otras muy comunes, no necesitan estar duplicadas en cada ejecutable, con la consiguiente economía de espacio. Los ejecutables resultan así más pequeños. Además, múltiples programas pueden compartir los mismos módulos.
Como ejemplo ilustrativo de lo anterior, podemos citar la utilidad Linux que permite encadenar (link) ficheros y directorios. Esta utilidad está disponible en dos versiones: La primera sln, utiliza enlazado estático; la segunda ln, enlazado dinámico. En mi sistema (SuSE 9.0), el tamaño de ambos ejecutables es el siguiente:
/sbin/sln 429308 Bytes
Linux dispone incluso de la utilidad ldd que permite conocer el tipo de enlazado que tiene un ejecutable y, en su caso, de qué módulos depende. En mi sistema obtengo el siguiente resultado para el encadenador dinámico [3]:
# ldd -v /bin/ln
libc.so.6 => /lib/i686/libc.so.6 (0x40028000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
Versioninformation:
/bin/ln:
libc.so.6 (GLIBC_2.3) => /lib/i686/libc.so.6
libc.so.6 (GLIBC_2.1.3) => /lib/i686/libc.so.6
libc.so.6 (GLIBC_2.1) => /lib/i686/libc.so.6
libc.so.6 (GLIBC_2.0) => /lib/i686/libc.so.6
libc.so.6 (GLIBC_2.2) => /lib/i686/libc.so.6
/lib/i686/libc.so.6:
ld-linux.so.2 (GLIBC_2.1) => /lib/ld-linux.so.2
ld-linux.so.2 (GLIBC_2.0) => /lib/ld-linux.so.2
ld-linux.so.2 (GLIBC_PRIVATE) => /lib/ld-linux.so.2
Librerías de enlazado dinámico:
Cuando los recursos a utilizar se encuentran en librerías de enlazado dinámico y en consecuencia, su ubicación exacta no puede ser establecida en tiempo de enlazado, se recurre a un artificio algo más tortuoso que en el caso de enlazado estático. En principio, la información sobre la localización de las funciones externas, están contenidas en las denominadas librerías de importación que tienen la misma terminación .lib/.a que las librerías normales, aunque en realidad, no contienen código, sino registros con el nombre del módulo que contiene la función (fichero .dll), así como el nombre o número del punto de entrada a la función dentro del fichero. El enlazador busca en estas librerías de importación de la misma forma que lo hace con el resto de ficheros .obj, .res y .lib que se compilan. Cuando el enlazador encuentra esta información la anota en la forma que se describe a continuación y da el asunto por resuelto sin original ningún error de enlazado.
Nota: Las librerías de importación pueden contener datos sobre una o varias DLLs. En el caso de la programación C++ para Windows, esta situación es frecuentísima, ya que la mayor parte de propio Sistema Operativo está repartido en multitud de DLLs. En dicho Sistema, las librerías de importación más importantes estén en los ficheros kernel32.lib; user32.lib ygdi32.lib. Recordar también que entre las herramientas que acompañan al compilador C++ de Borland, está la utilidad implib.exe, que puede crear una librería de importación a partir de una DLL. El resto de compiladores suelen disponer de herramientas análogas.
Los compiladores C++ construyen en cada ejecutable una tabla de entradas que contiene la dirección de todas las funciones de dirección conocida, y además, para poder realizar el enlazado dinámico, con la información obtenida de las librerías de importación construyen otra tabla denominada Tabla de Direcciones Importadas o Itable ("ImportAddressTable"). Cada función cuya dirección no pueda ser conocida en tiempo de compilación, tiene un sitio en la tabla, en el que se inserta un pequeño trozo de código ("thunk") que más tarde, en tiempo de ejecución, podrá establecer la verdadera dirección.
La invocación de una función como func1 que esté situada en una librería de enlazado dinámico, da lugar a un "thunk" del siguiente aspecto:
jmp DWORD PTR __imp_func1
En este caso __imp_func1 es una dirección conocida: la del "slot" de func1 en la tabla de direcciones importadas del ejecutable. Para que todo funcione correctamente solo es preciso que el cargador de la DLL, que utiliza la información obtenida de la librería de importación, actualice dicha tabla en el momento de la carga.
Funciones Virtual:
También existen situaciones en las que es preciso utilizar enlazado dinámico aunque el ejecutable no utilice DLLs. En la POO se presentan situaciones en las que se programan operaciones (mediante funciones virtuales) cuya definición es distinta para distintos objetos. En estos casos, cuando se necesita que un objeto ejecute uno de sus métodos, el código que deberá llamarse no está determinado hasta el momento de la ejecución, porque depende del objeto que realiza la invocación.
Los compiladores pueden utilizar cualquier mecanismo para resolver el problema, pero el más común consiste en la utilización de tres elementos:
• Para cada clase en la que existan métodos susceptibles de este comportamiento (métodos virtuales), se crea una tabla denominada vtable [2], de punteros con las direcciones de dichas funciones. La vtable realiza en este caso la misma función que la Itable cuando el programa utiliza enlazado dinámico debido a la existencia de librerías DLL.
• En cada objeto que se instancia de estas clases, se incluye automáticamente un puntero oculto vptr a la vtable.
• En cada invocación a un método de un objeto, se añade un pequeño trozo de código ("thunk"), que permite calcular la dirección de la función que debe utilizarse. Este código suele ser pequeño, contiene solo unas pocas instrucciones ensamblador, y utiliza la vtable y el vptr para seleccionar en tiempo de ejecución la función correspondiente. Cada objeto puede comportarse de forma distinta según este código especial. Así que cuando se le envía un mensaje, es este código el que calcula y decide que hacer con el mensaje (el proceso se describe con más detalle al tratar de las funciones virtuales 4.11.8a). Naturalmente esta versatilidad tiene su coste de eficacia, de forma que las funciones con enlazado dinámico sonmenos eficientes que las de enlazado estático.
En C++ el programador puede decidir en que funciones desea esta capacidad de enlazado retrasado utilizando la palabra-clave virtual. Cada vez que en una clase C se declara una función virtual, la case deviene en polimórfica ( 4.11.8) o abstracta ( 4.11.8c), lo que obliga al compilador a incluir en la estructura de la clase un puntero vptr que señala a una estructura de tipo matriz, la vtable, que contiene un "slot" o espacio para un puntero-a-función por cada función virtual que se haya declarado. Si C es a su vez derivada de una clase-base B, la vtable incluye espacio para las direcciones de cualquier función virtual que pudiera existir en B y en cualquier clase antecesora de esta. A su vez, obliga también a incluir una vtable en cualquier clase derivada de C. Existe una sola vtable para cada clase y los datos (punteros-a-función) contenidos en ella son estáticos, en el sentido de que no dependen de ninguna instancia u objeto particular de la clase.
Ejemplo:
Consideremos un caso de utilización de funciones virtuales en un supuesto de herencia simple (los casos de herencia múltiple requieren esquemas más complicados):
Fig. 1
class A {
int a:
virtualvoid foo1(int);
virtualvoid foo2(int);
virtualvoid foo3(int);
};
class B : public A {
int b;
void foo2(int);
};
class C : public B {
int c;
void foo3(int);
};
La figura adjunta muestra un esquema de lo que puede ser la zona contigua de memoria que contiene una instancia de C. Junto con el resto de miembros, privativos y heredados, se incluye el puntero oculto vptr que señala a la vtable. Observe que en realidad las funciones-miembro no forman parte del objeto-instancia, sino del objeto-clase.
No es necesario entender los mecanismos subyacentes para utilizarla, pero sin ella no es posible la programación orientada a objetos en C++ (recuérdese que en este sentido, C++ es un lenguaje mixto). Es preciso recordarlo porque por defecto las funciones miembro no tienen este tipo de enlazado dinámico. Son precisamente las funciones virtuales ( E4.11.8a) las que hacen posible diferentes comportamientos entre distintas clases de la misma familia; diferencias que a fin de cuentas definen el comportamiento polimórfico. Seguramente esta es la razón por la que mucha gente considera la palabra-clave virtual como la más importante y característica del lenguaje C++ frente al C.
Nota: En relación con este tema existe varios artículos: "ATL Underthe Hood" de ZeeshanAmjad, publicados en TheCodeProject , que recomiendo vivamente si desea una visión más cercana de cómo está constituida la vtable. Aunque dedicados a la Active Template Library (ATL), los dos primeros artículos de la serie muestra de forma muy didáctica las interioridades de la tabla de funciones virtuales y cómo puede ser accedida.
Atributos de enlazado:
Todos los identificadores tienen alguno de los tres atributos de enlazado (estrechamente relacionados con su ámbito): externo, interno, o sin enlazado. Estos atributos son propios para cada identificador en cada unidad de compilación, y vienen determinados por la situación y el formato de la declaración en que se introdujo cada identificador, así como del uso explícito o implícito (por defecto) de los especificadores de tipo de almacenamiento static y extern.
El tipo de enlazado define una especie de ámbito, pues indica si el mismo nombre en otro ámbito se refiere al mismo objeto (variable o función) o a otro distinto.
• Cada instancia de un identificador con enlazado externo representa el mismo objeto o función a través del total de ficheros y librerías que componen el programa. Es el tipo de enlazado a utilizar con objetos cuyo identificador puede ser utilizado en unidades de compilación distinta de aquella en la que se ha definido. Por esta razón se dice que las etiquetas con enlazado externo son "globales" para el programa.
Recuerde: enlazado externo ↔ visibilidad global.
• Cada instancia de un identificador con enlazado interno representa el mismo objeto o función solo dentro del mismo fichero. Los objetos con el mismo nombre en otros ficheros son objetos distintos. Este tipo de objetos solo pueden utilizarse en la unidad de compilación en que se han definido, por lo que suele decirse que las etiquetas con enlazado interno son "locales" a sus unidades de compilación.
Recuerde: enlazado interno ↔ visibilidad de fichero.
• Las unidades sin enlazado representan entidades únicas. Por ejemplo, las variables declaradas dentro de un bloque, que no contengan el modificador extern, representan entidades únicas dentro del bloque, sin relación con nada en el exterior del mismo. Los objetos con el mismo nombre en otros bloques son objetos distintos. No obstante, es posible asignar punteros a este tipo de objetos sin enlazado, de forma que puedan ser accedidos desde cualquier punto del programa, incluso desde otras unidades de compilación.
Como puede verse, el hecho que un identificador utilizado en diversas unidades de compilación señale potencialmente a la misma entidad en todos los módulos, depende exclusivamente del tipo de enlazado que tenga en cada uno de ellos.
Reglas de enlazado:
• En un fichero, cualquier objeto o identificador que tenga ámbito global deberá tener enlazado interno si su declaración contiene el especificador static.
• Si el mismo identificador aparece con ambos enlazados externo e interno, dentro del mismo fichero, tendrá enlazado externo.
• Si en la declaración de un objeto o función aparece el especificador de tipo de almacenamiento extern, el identificador tiene el mismo enlazado que cualquier declaración visible del identificador con ámbito global. Si no existiera tal declaración visible, el identificador tiene enlazado externo.
• Si una función es declarada sin especificador de tipo de almacenamiento, su enlazado es el que correspondería si se hubiese utilizado extern ( es decir, extern se supone por defecto en los prototipos de funciones).
• Si un objeto (que no sea una función) de ámbito global a un fichero es declarado sin especificar un tipo de almacenamiento, dicho identificador tendrá enlazado externo (ámbito de todo el programa). Como excepción, los objetos declarados const que no hayan sido declarados explícitamente extern tienen enlazado interno.
Los identificadores que respondan a alguna de las condiciones que siguen tienen un atributo sin enlazado:
a) Cualquier identificador distinto de un objeto o una función (por ejemplo, un identificador typedef ).
b) Parámetros de funciones.
c) Identificadores para objetos de ámbito de bloque, entre corchetes { } , que sean declarados sin el especificador de clase extern.
Ejemplo:
int x;
staticst = 0;
voidfunc(int);
intmain() {
for (x = 0; x < 10; x++) func(x);
}
voidfunc(int j) {
st += j;
cout<<st<<endl;
Comentario:
Las etiqueta x tiene enlazado externo debido a su situación en el código, fuera de cualquier bloque o función. Podría ser utilizada desde cualquier otro módulo que la declarase a su vez comoextern.
Las etiqueta func tiene igualmente enlazado externo debido a su situación en el código.
La variable j, pertenece exclusivamente al ámbito de la función func, por lo que es sin enlazado.
La variable st tiene enlazado interno. Debido al especificador static. solo es accesible desde dentro de su propio módulo.