13 Lien

Processus de liaison statique

La liaison statique est une méthode de liaison de bibliothèques lors de la compilation d'un programme. Pendant le processus de liaison statique, les fichiers de bibliothèque requis par le programme sont intégrés dans le fichier exécutable final. De cette façon, le programme n'a pas besoin de charger dynamiquement des fichiers de bibliothèque externes lors de son exécution. Le processus de liaison statique comprend principalement les étapes suivantes :

  • Compilez le code source : Tout d’abord, compilez le code source dans des fichiers objets. Un compilateur (tel que GCC) traduit les fichiers de code source (tels que les fichiers C ou C++) en code machine. Chaque fichier de code source générera un fichier objet correspondant.
  • Lier les fichiers de bibliothèque : l'éditeur de liens (tel que ld) liera le fichier objet au fichier de bibliothèque statique (généralement un fichier .a). Un fichier de bibliothèque statique est en fait un fichier d'archive contenant plusieurs fichiers objets. Ces fichiers objets contiennent l'implémentation des fonctions de bibliothèque requises par le programme.
  • Résolution des symboles : l'éditeur de liens recherche et résout les symboles (tels que les fonctions et les variables) utilisés dans le programme dans les fichiers objets et les fichiers de bibliothèque statiques. L'éditeur de liens fait correspondre ces symboles avec leur implémentation dans la bibliothèque.
  • Fusionner les fichiers objets : l'éditeur de liens fusionnera tous les fichiers objets et fichiers objets associés dans le fichier de bibliothèque statique pour générer un seul fichier exécutable. Ce fichier exécutable contient tout le code et les données du programme, y compris l'implémentation des fonctions de la bibliothèque.
  • Relocalisation : l'éditeur de liens détermine l'adresse mémoire finale de chaque symbole dans le fichier objet fusionné et met à jour les références à ces symboles. Ce processus est appelé relocalisation.
  • Générer un fichier exécutable : L'éditeur de liens génère enfin un fichier exécutable (tel qu'un fichier .exe ou ELF), qui contient tout le code et les données du programme. Ce fichier peut être exécuté directement sur la plateforme cible sans fichiers de bibliothèque supplémentaires.

Les avantages de la liaison statique incluent l'indépendance (le programme peut s'exécuter sur un système sans fichiers de bibliothèque) et les performances (le programme n'a pas besoin de charger dynamiquement les fichiers de bibliothèque lors de son démarrage et de son exécution). Cependant, la liaison statique présente également certains inconvénients, tels que le fichier exécutable généré est plus volumineux (car il contient l'implémentation de la bibliothèque) et le programme doit être recompilé et lié lorsque la bibliothèque est mise à jour.

Pourquoi utiliser des liens ?

La création de liens est une étape importante dans le processus de développement d’un programme. La liaison est principalement utilisée pour connecter les fichiers objets compilés et les fichiers de bibliothèque entre eux pour former un programme exécutable complet. Les raisons d'utiliser des liens incluent principalement des considérations de modularité, d'efficacité et de réutilisation du code :
(1) Modularité : La modularité est un concept important dans le développement de logiciels, qui peut nous aider à décomposer des systèmes complexes en composants faciles à gérer et à entretenir. Grâce à la liaison, les programmeurs peuvent diviser le code source en plusieurs modules indépendants (fichiers sources) et les compiler respectivement dans des fichiers cibles. L'éditeur de liens réunit ces fichiers objets pour former un programme complet. De cette façon, lorsqu'un module doit être modifié, seul ce module doit être recompilé sans avoir à recompiler l'intégralité du programme.
(2) Efficacité : les liens peuvent améliorer l’efficacité du développement. Lorsqu'une certaine partie du programme doit être modifiée, seule cette partie doit être recompilée sans recompiler l'intégralité du programme. L'éditeur de liens connectera les fichiers objets compilés et les fichiers de bibliothèque pour former un nouveau programme exécutable. De cette façon, les programmeurs peuvent itérer et déboguer plus rapidement.
(3) Réutilisation du code : les liens peuvent facilement réutiliser les bibliothèques de codes existantes. Les programmeurs peuvent encapsuler des fonctions et des structures de données couramment utilisées dans des fichiers de bibliothèque pour les utiliser dans plusieurs projets. L'éditeur de liens connecte ces fichiers de bibliothèque aux fichiers objets afin que le programme puisse appeler des fonctions et des données dans la bibliothèque. Cela évite d'écrire le même code à plusieurs reprises et améliore l'efficacité du développement.
(4) Économisez de la mémoire et de l'espace disque : en reliant des bibliothèques dynamiques (telles que des fichiers .so ou .dll), plusieurs programmes peuvent partager le même fichier de bibliothèque, réduisant ainsi l'utilisation de la mémoire et l'espace disque. La liaison dynamique permet à un programme de charger des fichiers de bibliothèque au moment de l'exécution, de sorte que les fichiers de bibliothèque ne soient chargés en mémoire que lorsque le programme utilise réellement les fonctions de la bibliothèque. Cela contribue à améliorer l’utilisation des ressources système.

En bref, la liaison est un maillon clé dans le processus de développement de programmes, qui permet de réaliser la modularisation, d'améliorer l'efficacité du développement, de réaliser la réutilisation du code et d'économiser de la mémoire et de l'espace disque.

Le rôle des connecteurs

L'éditeur de liens est un composant important de la chaîne d'outils d'un langage de programmation. Il est chargé de connecter les fichiers objets et les fichiers bibliothèque générés après la compilation pour générer le fichier exécutable final ou fichier bibliothèque. Les principales fonctions des connecteurs comprennent :

  • Analyse des symboles : les fonctions et les variables d'un programme sont appelées symboles. Le connecteur analyse les fichiers objets et les fichiers de bibliothèque pour trouver les relations de référence de symboles entre eux et fait correspondre les symboles utilisés avec leur implémentation dans la bibliothèque. Ce processus est appelé résolution de symboles.
  • Fusionner les fichiers objets : le connecteur combine plusieurs fichiers objets et fichiers objets dans des fichiers de bibliothèque en un seul fichier. Ce fichier peut être un fichier exécutable (tel qu'un fichier .exe ou ELF) ou un fichier de bibliothèque (tel qu'un fichier .a, .so ou .dll).
  • Relocalisation : lors du processus de fusion des fichiers objets, le connecteur attribue une adresse mémoire à chaque symbole. La relocalisation fait référence à la mise à jour de la référence au symbole dans le fichier cible afin qu'il pointe vers l'adresse mémoire correcte. Ce processus implique la gestion de deux types de références, les adresses absolues et les adresses relatives.
  • Générer un fichier exécutable : Le connecteur va enfin générer un fichier exécutable

Résolution des symboles
La résolution des symboles est une étape clé du processus de liaison, qui implique de faire correspondre les symboles (tels que les fonctions et les variables) dans le code source avec leur implémentation réelle dans le fichier objet ou le fichier bibliothèque. Pendant le processus de compilation, le code source sera traduit en fichiers objets, mais le compilateur ne connaît pas les adresses spécifiques de ces symboles dans le programme final, donc certaines références de symboles non résolues seront générées.

Au cours du processus de liaison, le connecteur doit effectuer les tâches de résolution de symboles suivantes :

  • Recherchez les définitions de symboles : l'éditeur de liens analyse tous les fichiers objets d'entrée et les fichiers de bibliothèque pour trouver la définition de chaque symbole non résolu. Ces définitions peuvent provenir d'autres fichiers objets ou fichiers de bibliothèque.
  • Résoudre les conflits de symboles : lorsqu'un symbole portant le même nom existe dans plusieurs fichiers objets ou fichiers de bibliothèque, l'éditeur de liens doit décider quelle définition utiliser. Cela implique généralement de gérer les relations de préséance entre les symboles faibles et forts. Les symboles forts sont généralement choisis pour la définition finale, de préférence aux symboles faibles.
  • Le connecteur construira une table de symboles pour enregistrer le nom, le type et l'adresse de chaque symbole.

réinitialiser

  • La relocalisation pendant le processus de liaison fait référence au processus dans lequel le système d'exploitation convertit les adresses virtuelles des symboles (tels que les fonctions, les variables, etc.) référencés dans le programme en adresses physiques réelles lorsque le programme est chargé.

Lors du développement d'un programme, il est souvent nécessaire d'appeler des fonctions ou des variables dans des bibliothèques ou modules externes. Les codes de ces bibliothèques ou modules externes ne sont pas dans les fichiers de code du programme en cours, et ils doivent être combinés avec le code du programme en cours. programme via des liens. Au moment de la liaison, le compilateur fait correspondre les symboles externes référencés dans le programme actuel avec les symboles réels dans la bibliothèque ou le module externe et enregistre l'adresse virtuelle du symbole référencé dans la table des symboles du programme. Lorsque le programme est en cours d'exécution, le système d'exploitation mappera l'adresse virtuelle du programme à l'adresse physique réelle et remplacera l'adresse virtuelle dans la table des symboles du programme par l'adresse physique réelle, complétant ainsi le processus de relocalisation.

  • Le processus de relocalisation est généralement complété par l'éditeur de liens dynamique du système d'exploitation. L'éditeur de liens dynamique déplacera dynamiquement les symboles dans le programme lorsque le programme est chargé et définira le point d'entrée du programme à l'adresse initiale du programme.

.o module cible déplaçable

"Module objet relocalisable" est un concept dans les domaines de l'informatique et du génie logiciel. Il fait référence à un module qui peut être lié à d'autres modules objets pour créer un fichier exécutable ou une bibliothèque pendant le processus de liaison du programme. Fichier cible. Les modules objets déplaçables contiennent des parties de programmes (telles que des fonctions, des données, etc.) qui sont stockées au format binaire après la compilation.

Lorsqu'un compilateur compile le code source, il compile généralement chaque fichier source dans un module objet déplaçable. Ces modules contiennent des parties d'un programme conçues pour être combinées avec d'autres modules objets pendant la phase de liaison. L'éditeur de liens gère des tâches telles que la résolution de symboles, le calcul d'adresses et la relocalisation entre ces modules, en les fusionnant dans un exécutable ou une bibliothèque complète.

Le principal avantage des modules objets déplaçables est la modularité. Ils permettent aux programmeurs de diviser des programmes volumineux en plusieurs fichiers sources, ce qui facilite l'organisation et la maintenance du code. De plus, les modules cibles déplaçables peuvent être partagés sur plusieurs projets, permettant la réutilisation du code et réduisant les temps de compilation.

Fichier exécutable .out

"Fichier exécutable" est un type spécial de fichier utilisé par le système d'exploitation de l'ordinateur pour exécuter des programmes. Ces fichiers contiennent le code du programme compilé (code machine), ainsi que les données et ressources nécessaires à l'exécution du programme. Dans différents systèmes d'exploitation, les fichiers exécutables ont des extensions de fichier différentes. Par exemple, dans les systèmes Windows, l'extension des fichiers exécutables est généralement .exe ; dans les systèmes Linux et Unix, les fichiers exécutables n'ont pas d'extension spécifique. Mais généralement avec des autorisations d'exécutable.
Le processus de compilation du code source dans un fichier exécutable implique généralement les étapes suivantes :

  • Compilation : les programmeurs écrivent du code source (tel que des langages de programmation tels que C, C++, Java, etc.), puis utilisent un compilateur pour convertir le code source en code cible (généralement du code machine ou du bytecode).
  • Liaison : liez le code objet compilé (module objet déplaçable) avec d'autres modules objet nécessaires (tels que les fichiers de bibliothèque) pour générer un fichier exécutable complet. L'éditeur de liens est chargé de résoudre des problèmes tels que les références de symboles et l'allocation d'adresses entre les modules.
  • Chargement : lors de l'exécution d'un programme, le système d'exploitation charge le fichier exécutable en mémoire, alloue les ressources nécessaires à son exécution et exécute le programme dans l'espace d'adressage approprié.

Les fichiers exécutables contiennent généralement les parties suivantes

  • En-tête : contient les métadonnées du fichier, telles que le format de fichier, la plate-forme cible, le point d'entrée du programme, etc.
  • Segment de code : Contient le code machine d'un programme, les instructions réellement exécutées.
  • Segment de données : contient les variables globales et les variables statiques requises lors de l'exécution du programme.
  • Segment de ressources : contient les ressources nécessaires à l'exécution du programme, telles que des images, des icônes, des chaînes, etc.

Le format du fichier exécutable varie en fonction du système d'exploitation et de la plate-forme cible. Par exemple, les fichiers exécutables sur les systèmes Windows utilisent généralement le format PE (Portable Executable), tandis que les fichiers exécutables sur les systèmes Linux et Unix utilisent généralement le format ELF (Executable and Linkable Format).

.so fichier objet partagé

"Shared Object File" (Shared Object File), également connu sous le nom de "Dynamic Link Library" (DLL en abrégé) dans le système d'exploitation Windows, est un type spécial de fichier objet déplaçable qui peut être utilisé dans le programme. Le runtime est chargé dynamiquement en mémoire et lié. Les fichiers d'objets partagés contiennent généralement des fonctions et des données réutilisables dans un programme. Ils peuvent être partagés entre plusieurs programmes, réduisant ainsi l'utilisation des ressources système et améliorant la réutilisabilité du code.

Dans les systèmes Unix et de type Unix (tels que Linux), les fichiers objets partagés ont généralement une extension .so (par exemple, libfoo.so). Sur les systèmes Windows, les bibliothèques de liens dynamiques ont une extension .dll (par exemple, foo.dll).

Les principaux avantages des fichiers objets partagés sont les suivants :

  • Réutilisation du code : les mêmes fichiers de bibliothèque peuvent être partagés entre plusieurs programmes pour réduire l'utilisation des ressources système.
  • Facile à mettre à jour : lorsqu'un fichier de bibliothèque doit être mis à jour, il vous suffit de remplacer le fichier objet partagé sans recompiler le programme qui l'utilise.
  • Utilisation réduite de la mémoire : plusieurs programmes peuvent partager des instances en mémoire du même fichier de bibliothèque, réduisant ainsi l'utilisation globale de la mémoire.

L'utilisation de fichiers objets partagés implique les étapes suivantes :

  • Compilation : les programmeurs écrivent le code source et utilisent un compilateur pour compiler le code source dans des fichiers objets partagés.
  • Liaison : lors de la compilation d'un programme, l'éditeur de liens intègre des références aux fichiers objets partagés dans le fichier exécutable résultant. Ces références sont généralement indirectes afin qu'elles puissent être résolues au moment de l'exécution.
  • Chargement : lorsqu'un programme s'exécute, le système d'exploitation vérifie l'exécutable pour les références aux fichiers objets partagés, puis charge ces fichiers objets partagés en mémoire (s'ils ne sont pas déjà chargés) et exécute le programme dans l'espace d'adressage approprié. Si le fichier objet partagé est déjà chargé en mémoire, les programmes partagent la même instance.

Pendant le processus de développement, les programmeurs doivent prêter attention aux problèmes de compatibilité des versions de fichiers objets partagés. Lorsqu'un objet partagé est mis à jour, vous devez vous assurer que sa nouvelle version est compatible avec l'ancienne version pour éviter des problèmes avec les programmes qui l'utilisent.

Module cible norme ELF

ELF (Executable and Linkable Format) est un format de fichier courant pour les fichiers exécutables, les fichiers objets déplaçables et les fichiers objets partagés. Il est largement utilisé dans de nombreux systèmes d'exploitation Unix et de type Unix (tels que Linux, FreeBSD, Solaris, etc.). La norme ELF vise à fournir un format de fichier binaire flexible, extensible et multiplateforme.

Le format de fichier ELF présente les caractéristiques suivantes :

  • En-tête de fichier : contient des métadonnées sur le type de fichier (fichier exécutable, fichier objet transférable ou fichier objet partagé), le type de machine cible, la version du fichier, etc. L'en-tête du fichier contient également des informations d'emplacement de la table d'en-tête du programme et de la table d'en-tête de section.

+ Section : les fichiers ELF sont organisés en plusieurs sections, chaque section contient différentes parties du programme (telles que des segments de code, des segments de données, etc.). Le tableau d'en-tête de section décrit les attributs et les informations d'emplacement de toutes les sections du fichier.

+Tableau d'en-tête du programme : existe uniquement dans les fichiers exécutables et les fichiers objets partagés. Il décrit comment le programme mappe des parties du fichier en mémoire au moment de l'exécution. Chaque entrée décrit un segment de mémoire (Segment) et contient des informations sur le type du segment, les droits d'accès, le décalage dans le fichier et l'emplacement en mémoire.

+Tableau des symboles : contient des informations sur les fonctions, les variables et autres symboles dans le code source. L'éditeur de liens utilise ces informations pour résoudre les références de symboles et lier les modules d'objets déplaçables entre eux.

+Tableau de relocalisation : contient les références d'adresses qui doivent être corrigées lors du processus de liaison. Ces références pointent généralement vers des symboles dans d'autres modules. L'éditeur de liens corrige ces références d'adresse en fonction de la table des symboles et de la table de relocalisation.

+Tableau de chaînes : contient les chaînes utilisées dans le fichier (telles que les noms de symboles, les noms de sections, etc.). Les noms dans la table des symboles et dans la table des en-têtes de section pointent généralement vers des chaînes dans la table des chaînes.

+Informations de débogage : les fichiers ELF peuvent contenir des informations de débogage pour fournir des informations au niveau du code source lors du débogage. Ces informations sont généralement stockées dans des sections de débogage spéciales, telles que le format DWARF.

Le standard ELF est conçu pour être facilement extensible et adaptable à différentes plateformes cibles. Dans les applications réelles, l'implémentation du format de fichier ELF peut varier en fonction du système d'exploitation, de l'architecture matérielle et du compilateur.

Classification des symboles de liaison

L'éditeur de liens est chargé de relier plusieurs fichiers objets et fichiers de bibliothèque pour générer un fichier exécutable ou un fichier de bibliothèque. Au cours du processus de liaison, l'éditeur de liens doit gérer divers symboles, tels que des fonctions, des variables, etc. L'éditeur de liens trie les symboles afin qu'ils puissent être analysés et liés correctement. Les classifications de symboles courants sont les suivantes :

  • Symboles locaux : les symboles locaux sont visibles dans le fichier source ou cible dans lequel ils sont définis, mais pas dans les autres fichiers. Ces symboles incluent généralement des fonctions et des variables déclarées statiques en C ou C++. Les symboles locaux n'ont pas besoin d'être résolus pendant le processus de liaison car ils ne sont valides que dans la portée locale.
  • Symboles globaux : les symboles globaux sont visibles dans les fichiers source ou cible dans lesquels ils sont définis, et sont également visibles dans d'autres fichiers. Ces symboles incluent des fonctions et des variables non statiques. Les symboles globaux doivent être résolus lors du processus de liaison car ils peuvent être référencés dans d'autres fichiers objets.
    Les symboles globaux sont divisés en :
    a. Symboles forts : les symboles forts sont généralement des variables et des fonctions définies qui ont alloué un espace de stockage. Pendant le processus de liaison, les symboles forts ont une priorité plus élevée. Si des symboles forts portant le même nom existent dans plusieurs fichiers objets, l'éditeur de liens signalera une erreur.

B. Symboles faibles : les symboles faibles sont généralement des variables avec un espace de stockage non alloué et des fonctions non définies. Pendant le processus de liaison, les symboles faibles ont une priorité inférieure. S'il existe des symboles forts et des symboles faibles portant le même nom dans plusieurs fichiers objets, l'éditeur de liens sélectionnera le symbole fort.

  • Symboles externes : les symboles externes sont des symboles globaux définis dans d'autres fichiers objets ou fichiers de bibliothèque. Au cours du processus de liaison, l'éditeur de liens doit trouver les définitions de ces symboles et les résoudre. Si l'éditeur de liens ne parvient pas à trouver une définition pour un symbole externe, une erreur de symbole non résolue sera signalée.

L'éditeur de liens gère divers problèmes de référence et de résolution de symboles via la classification des symboles. Au cours du processus de liaison, l'éditeur de liens détermine comment analyser et lier ces symboles en fonction de leur visibilité, de leur priorité et d'autres attributs.

Comparaison des variables locales non statiques et des variables statiques locales

Les variables locales non statiques et les variables statiques locales sont deux types différents de variables locales, et leurs fonctions et caractéristiques dans le programme sont différentes. Ce qui suit est une comparaison des variables locales non statiques et des variables statiques locales :

  1. Cycle de vie
    + variable locale non statique (Local Non-static Variable) : Le cycle de vie d'une variable locale non statique se déroule lors de l'exécution de la fonction ou du bloc de code dans lequel elle est définie. Lorsque la fonction ou le bloc de code termine son exécution, les variables locales non statiques sont détruites. La prochaine fois que vous entrerez dans la fonction ou le bloc de code, les variables locales non statiques seront recréées et la mémoire sera réaffectée.
    + Variable statique locale : Le cycle de vie des variables statiques locales commence du début de l'exécution du programme à la fin du programme. Même si la fonction ou le bloc de code dans lequel elle est définie est exécuté, la variable statique locale existe toujours. La prochaine fois que la fonction ou le bloc de code sera saisi, la variable statique locale conservera la dernière valeur.
  2. Emplacement de stockage
    + variables locales non statiques : les variables locales non statiques sont généralement stockées sur la pile. L'allocation de mémoire sur la pile est plus rapide, mais l'espace est limité.
    + Variables statiques locales : les variables statiques locales sont généralement stockées dans la zone de stockage statique ou le segment de données global. La mémoire de ces zones ne sera pas libérée lors de l'exécution du programme.
  3. Initialisation
    + variables locales non statiques : Une variable locale non statique est réinitialisée à chaque fois qu'elle entre dans la fonction ou le bloc de code dans lequel elle est définie. S'ils ne sont pas initialisés explicitement, leurs valeurs seront indéfinies.
    + Variables statiques locales : Les variables statiques locales ne sont initialisées qu'une seule fois lors de l'exécution du programme. S'ils ne sont pas initialisés explicitement, ils sont automatiquement initialisés à 0 (pour les types entiers) ou NULL (pour les types pointeur).
  4. Visibilité
    + variables locales non statiques : Une variable locale non statique est visible au sein de la fonction ou du bloc de code dans lequel elle est définie. Ces variables ne sont pas accessibles en dehors de la fonction ou du bloc de code.
    + Variables statiques locales : les variables statiques locales sont également visibles dans la fonction ou le bloc de code dans lequel elles sont définies. Bien que leur durée de vie soit plus longue que les variables locales non statiques, leur visibilité reste limitée.

En résumé, il existe des différences significatives entre les variables locales non statiques et les variables statiques locales en termes de durée de vie, d'emplacement de stockage, d'initialisation et de visibilité. En fonction des besoins du programme et du comportement attendu, les développeurs peuvent choisir le type approprié de variables locales.

Comment l'éditeur de liens résout-il le problème des symboles en double dans une définition ? Symbole fort, symbole faible

L'éditeur de liens peut rencontrer des problèmes de définitions de symboles en double lors du traitement de plusieurs fichiers objets. Pour résoudre ce problème, l'éditeur de liens s'appuie sur une classification des symboles : Symboles Forts et Symboles Faibles. Voici comment l'éditeur de liens gère le problème des définitions de symboles en double :

  • Symboles forts par rapport aux symboles forts : si l'éditeur de liens trouve un symbole fort portant le même nom dans deux fichiers objets ou plus (par exemple, une variable avec un stockage alloué ou une fonction définie), il signalera une erreur de lien indiquant qu'il y a Plusieurs définitions. Dans ce cas, le développeur doit vérifier le code source pour trouver les définitions en double et les corriger.
  • Symboles forts ou faibles : lorsque l'éditeur de liens rencontre un symbole fort et un ou plusieurs symboles faibles portant le même nom, il sélectionne le symbole fort et ignore tous les symboles faibles portant le même nom. En effet, les symboles forts ont une priorité plus élevée. Dans ce cas, l'éditeur de liens ne signale pas d'erreur mais poursuit le processus de liaison.
  • Symboles faibles contre symboles faibles : si l'éditeur de liens trouve deux symboles faibles ou plus portant le même nom, il en sélectionnera arbitrairement un et ignorera les autres symboles faibles. L'éditeur de liens ne signale pas d'erreur mais continue le processus de liaison.

De cette manière, l’éditeur de liens utilise une classification de symboles forts et faibles pour résoudre le problème des définitions de symboles en double. Les symboles forts ont une priorité plus élevée, tandis que les symboles faibles peuvent être écrasés par des symboles forts lors du processus de liaison. Les développeurs doivent veiller à éviter les définitions répétées de symboles lors de l'écriture du code afin de garantir un comportement correct des liens et du programme.

Raisons d'éviter les variables globales

Les variables globales sont visibles et accessibles dans l'ensemble du programme et, même si leur utilisation peut être pratique dans certaines situations, leur utilisation excessive peut entraîner certains problèmes. Voici les principales raisons d’éviter d’utiliser des variables globales :

  • Maintenabilité : trop de variables globales peuvent rendre un programme difficile à maintenir. Étant donné que les variables globales sont accessibles et modifiées n'importe où dans le programme, il peut être difficile de suivre leur utilisation. Cela peut donner lieu à un code difficile à comprendre et à modifier.
  • Conflits de noms : les variables globales partagent le même espace de noms, ce qui peut entraîner des conflits de noms. Lorsqu'un programme devient volumineux ou implique plusieurs développeurs, différents développeurs peuvent choisir les mêmes noms pour les variables globales, provoquant des erreurs et de la confusion.
  • Modularité : Les variables globales détruisent la modularité du code, rendant floues les dépendances entre modules. La modularité est un principe important de la conception logicielle qui permet de diviser un programme en parties pouvant être développées, testées et réutilisées indépendamment. Trop de variables globales entraîneront des dépendances implicites entre les modules et réduiront la réutilisabilité du code.
  • Problèmes de concurrence : dans un environnement multithread, les variables globales peuvent provoquer des courses de données et des problèmes de synchronisation. Lorsque plusieurs threads tentent d'accéder et de modifier des variables globales en même temps, des états incohérents peuvent se produire. Afin d'éviter ces problèmes, les développeurs doivent utiliser des mécanismes de synchronisation tels que des verrous et des opérations atomiques, ce qui augmentera la complexité du code.
  • Difficulté de test : l'écriture de tests unitaires pour du code contenant des variables globales devient plus difficile car les variables globales sont accessibles à l'échelle du programme. Les variables globales peuvent provoquer des effets secondaires entre les tests, affectant ainsi les résultats des tests par d'autres tests.

Afin d'éviter ces problèmes, il est recommandé d'utiliser des variables locales, des paramètres de fonction, des valeurs de retour, des membres de classe, etc. au lieu de variables globales. Ces méthodes contribuent à améliorer la maintenabilité, la lisibilité et la réutilisation du code tout en réduisant les problèmes de concurrence et les difficultés de test. Lorsque vous avez vraiment besoin d'utiliser des variables globales, vous devez essayer de limiter leur nombre et leur portée, et suivre les principes d'encapsulation et de visibilité réduite.

Entrée de déménagement

L'entrée de relocalisation est une structure de données rencontrée par l'éditeur de liens lors du traitement d'un fichier objet. Lors de la compilation, le compilateur peut ne pas être en mesure de déterminer l'adresse exacte de certains symboles (tels que des variables ou des fonctions) dans le fichier exécutable final. Par conséquent, le compilateur crée une table de relocalisation (Relocation Table) lors de la génération du fichier objet, qui contient des références de symboles nécessitant une correction d'adresse lors de l'étape de liaison. Chaque référence de symbole à corriger correspond à une entrée de relocalisation.

Les entrées de réinstallation contiennent généralement les informations suivantes :

  1. Type de relocalisation : décrit comment la relocalisation est appliquée. Par exemple, certains types de relocalisation représentent l'ajout direct d'une adresse de symbole à l'emplacement de référence, tandis que d'autres types peuvent impliquer des calculs plus complexes.
  2. Décalage de relocalisation : spécifiez l'emplacement de l'adresse dans le fichier cible qui doit être corrigé. Ce décalage est relatif à une section (telle qu'une section de code ou une section de données) dans le fichier cible.
  3. Index des symboles : L'index des symboles dans la table des symboles du fichier cible. L'éditeur de liens peut trouver des informations sur les symboles liés à la relocalisation via cet index.

Au cours du processus de liaison, l'éditeur de liens parcourt les tables de relocalisation de tous les fichiers cibles et corrige les références de symboles en fonction des entrées de relocalisation dans la table. L'éditeur de liens recherche la table des symboles pour déterminer l'adresse finale du symbole, puis corrige la référence d'adresse dans le fichier objet en fonction du type de relocalisation et du décalage. Lorsque l'éditeur de liens termine l'opération de relocalisation, les références de symboles dans l'exécutable ou le fichier de bibliothèque généré pointent vers l'adresse correcte, permettant au programme d'accéder correctement aux variables et aux fonctions au moment de l'exécution.

Charger le fichier objet exécutable

Lorsqu'un fichier objet exécutable (par exemple, au format ELF ou au format PE) est chargé en mémoire et exécuté par le système d'exploitation, il passe par les étapes suivantes :

  • Lire les métadonnées du fichier exécutable : le système d'exploitation lit d'abord les métadonnées du fichier exécutable, telles que les en-têtes de fichier et les en-têtes de programme. Ces données contiennent des informations sur les différents segments du programme (tels que des segments de code, des segments de données) et des détails sur la manière dont ils sont chargés en mémoire.
  • Allouer de la mémoire : le système d'exploitation alloue de la mémoire pour chaque segment du programme en fonction des métadonnées du fichier exécutable. Généralement, le segment de code est chargé dans une zone de mémoire en lecture seule, tandis que le segment de données et le segment de pile sont chargés dans une zone de mémoire en lecture-écriture.
  • Chargement de segments de programme : Le système d'exploitation charge chaque segment de programme (segment de code, segment de données, etc.) du fichier exécutable dans la zone mémoire allouée. Pendant le processus de chargement, le système d'exploitation peut avoir besoin de traiter certaines informations de relocalisation pour corriger les références aux adresses mémoire dans le programme.
  • Résoudre les bibliothèques de liens dynamiques : si l'exécutable dépend de bibliothèques de liens dynamiques (par exemple, des bibliothèques partagées ou des fichiers DLL), le système d'exploitation charge ces bibliothèques et résout leurs symboles. Cela peut impliquer d'autres opérations de déplacement pour garantir que les références dans le programme aux fonctions et variables de la bibliothèque pointent vers les adresses correctes.
  • Initialiser la pile : le système d'exploitation alloue et initialise la mémoire de pile pour le programme. La pile est utilisée pour stocker des informations telles que les variables locales, les paramètres et les adresses de retour des appels de fonction.
  • Aller au point d'entrée du programme : Enfin, le système d'exploitation placera le compteur de programme (Program Counter) au point d'entrée du programme (généralement la fonction principale ou son équivalent) et commencera à exécuter le programme.

Au cours de ce processus, le système d'exploitation est responsable du chargement correct du fichier cible exécutable et de la fourniture d'un environnement d'exécution approprié pour le programme. Une fois le chargement terminé, le programme commence à s'exécuter jusqu'à ce qu'il rencontre une condition de fin (telle qu'un retour au système d'exploitation ou une fin anormale).

Fonctions couramment utilisées

Pour réutiliser les fonctions fréquemment utilisées dans plusieurs projets, vous pouvez regrouper ces fonctions dans une bibliothèque statique, une bibliothèque dynamique ou un fichier d'en-tête. Voici de brèves instructions pour créer et utiliser des bibliothèques de ces trois manières :

  1. Bibliothèques statiques :
    le regroupement des fonctions couramment utilisées dans des bibliothèques statiques (généralement des fichiers .a sur les systèmes Unix et des fichiers .lib sur les systèmes Windows) permet de lier ces fonctions aux fichiers objets d'autres projets. Les étapes pour créer une bibliothèque statique sont les suivantes :
    a. Écrivez un fichier de code source (tel qu'un fichier .c ou .cpp) contenant les fonctions couramment utilisées.
    b. Compilez les fichiers de code source dans des fichiers objets (tels que des fichiers .o ou .obj).
    c. Utilisez des outils de bibliothèque statique (tels que ar dans les systèmes Unix, lib dans les systèmes Windows) pour regrouper les fichiers cibles dans
    des fichiers .
    d. Lorsque vous utilisez des bibliothèques statiques dans d'autres projets, liez les fichiers de bibliothèque statique aux fichiers objets du projet.
  2. Bibliothèques dynamiques :
    le regroupement des fonctions couramment utilisées dans des bibliothèques dynamiques (généralement des fichiers .so sur les systèmes Unix et des fichiers .dll sur les systèmes Windows) permet à ces fonctions d'être chargées et liées dynamiquement au moment de l'exécution. Les étapes pour créer une bibliothèque dynamique sont les suivantes :
    a. Écrivez un fichier de code source (tel qu'un fichier .c ou .cpp) contenant les fonctions couramment utilisées.
    b. Utilisez les options du compilateur pour compiler les fichiers de code source dans des fichiers de bibliothèque dynamiques. Par exemple, en utilisant gcc sur un système Unix, vous pouvez utiliser l'option -shared pour créer une bibliothèque dynamique.
    c. Lorsque vous utilisez des bibliothèques dynamiques dans d'autres projets, assurez-vous que les fichiers de bibliothèque dynamique sont disponibles au moment de l'exécution. Le système d'exploitation doit être capable de trouver des fichiers de bibliothèque dynamiques dans des chemins de recherche prédéfinis.
  3. Fichiers d'en-tête :
    une autre façon de réutiliser les fonctions fréquemment utilisées consiste à les inclure directement dans un fichier d'en-tête (tel qu'un fichier .h ou .hpp). Cette approche fonctionne bien pour les petites fonctions, telles que les fonctions en ligne ou les fonctions de modèle. Placez simplement les fonctions dans un fichier d'en-tête, puis incluez le fichier d'en-tête dans les projets qui doivent utiliser ces fonctions.

Remarque : Lorsque vous choisissez un type de bibliothèque, vous devez peser le pour et le contre entre les bibliothèques statiques et dynamiques. Les bibliothèques statiques lient le code de fonction directement au programme cible, ce qui entraîne une augmentation de la taille du programme mais réduit les dépendances externes au moment de l'exécution. Les bibliothèques dynamiques sont chargées au moment de l'exécution, ce qui peut économiser de l'espace disque et de la mémoire, mais peut entraîner des problèmes de dépendance et des problèmes de compatibilité de version.

Bibliothèque de liens statiques

静态链接库是一种将编译后的目标文件打包成一个库文件的方式。这种库文件可以在链接阶段与其他目标文件链接在一起,形成最终的可执行文件。静态链接库中的函数和数据在编译时被嵌入到可执行文件中,使得生成的可执行文件独立于库文件。这样,在运行可执行文件时,不需要额外的共享库或动态链接库。
在 Unix-like 系统(如 Linux)中,静态链接库通常以 .a(代表 "archive")为文件扩展名,如 libexample.a。在 Windows 系统中,静态链接库通常以 .lib 为文件扩展名。

Les étapes générales pour créer une bibliothèque de liens statiques sont les suivantes :
1. Écrivez les fichiers de code source (tels que .c, .cpp) et implémentez les fonctions et données requises.
2. Compilez les fichiers de code source en fichiers cibles (tels que .o, .obj).
3. Utilisez un outil d'archivage (tel que ar dans les systèmes de type Unix, lib dans les systèmes Windows) pour regrouper le fichier cible dans une bibliothèque de liens statiques.

Les étapes générales d'utilisation d'une bibliothèque de liens statiques sont les suivantes :
1. Incluez la déclaration des fonctions et des données de la bibliothèque de liens statiques dans le code source (généralement dans le fichier d'en-tête).
2. Pendant le processus de compilation et de liaison, spécifiez le chemin et le nom de la bibliothèque de liens statiques afin que le compilateur et l'éditeur de liens puissent trouver et lier le fichier de bibliothèque.

Avantages des bibliothèques de liens statiques :
1. Le fichier exécutable généré contient toutes les fonctions et données requises, il ne dépend donc pas de fichiers de bibliothèques externes au moment de l'exécution. Cela simplifie le déploiement et la distribution.
2. Peut-être de meilleures performances car les appels de fonction sont directs sans nécessiter d'adressage indirect.
Inconvénients des bibliothèques de liens statiques :
1. Le fichier exécutable généré est plus volumineux car toutes les fonctions et données de la bibliothèque sont intégrées dans le fichier exécutable.
2. Lors de la mise à jour d'une bibliothèque, tous les programmes qui utilisent la bibliothèque doivent être recompilés et liés pour que la mise à jour prenne effet.

Pour résumer, les bibliothèques de liens statiques conviennent aux projets qui souhaitent regrouper toutes les dépendances dans un fichier exécutable autonome pour simplifier le processus de déploiement et de distribution. Cependant, des problèmes tels que l'augmentation de la taille des fichiers exécutables et les difficultés de mise à jour causées par les bibliothèques de liens statiques doivent être pris en compte.

Le processus de liaison de bibliothèque statique
Le processus de liaison de bibliothèque statique consiste à lier les fichiers objets de la bibliothèque statique avec d'autres fichiers objets pour former le fichier exécutable final. L'éditeur de liens résout les références symboliques au cours de ce processus, en les associant aux fonctions ou variables réelles de la bibliothèque. Voici les étapes détaillées du processus de liaison de bibliothèque statique :

1. Analyser les fichiers d'entrée : l'éditeur de liens reçoit un ensemble de fichiers d'entrée, qui incluent des fichiers objets (tels que des fichiers .o ou .obj) et des fichiers de bibliothèque statiques (tels que des fichiers .a ou .lib). L'éditeur de liens analyse d'abord ces fichiers pour comprendre les symboles, les informations de relocalisation, etc. contenus dans les fichiers.
2. Résolution des symboles : l'éditeur de liens commence à analyser les références et les définitions des symboles dans le fichier d'entrée. Pour chaque référence de symbole non résolue, l'éditeur de liens recherche dans le fichier d'entrée la définition de symbole correspondante. Pour les fichiers de bibliothèque statiques, l'éditeur de liens extrait uniquement les fichiers objets contenant les définitions de symboles requises. Cela signifie que les fonctions et données inutilisées dans la bibliothèque statique ne seront pas incluses dans l'exécutable final.
3. Allocation d'adresses : l'éditeur de liens alloue des adresses mémoire à chaque segment du fichier d'entrée (comme un segment de code, un segment de données, etc.). Lors de l'attribution d'adresses, l'éditeur de liens garantit que chaque segment dispose d'un alignement et de droits d'accès appropriés en mémoire (tels que lecture seule, lecture-écriture, etc.).
4. Relocalisation : l'éditeur de liens traite les informations de relocalisation dans le fichier d'entrée pour corriger la référence à l'adresse dans le programme. Cela peut inclure la mise à jour d'une instruction d'appel de fonction vers l'adresse cible correcte ou la mise à jour d'une référence de variable globale vers l'emplacement mémoire correct.
5. Générer le fichier de sortie : l'éditeur de liens fusionne le code et les données liés dans un nouveau fichier exécutable (tel que le format ELF ou PE). Ce fichier exécutable contient les fonctions et les données de tous les fichiers d'entrée, ainsi que les informations d'exécution générées par l'éditeur de liens (telles que les tables de symboles, les tables de relocalisation, etc.).
6. Optimisation (facultatif) : pendant le processus de liaison, l'éditeur de liens peut effectuer certaines opérations d'optimisation, telles que la suppression de fonctions et de données inutilisées, la fusion de constantes en double, etc. Ces optimisations peuvent réduire la taille des fichiers exécutables et améliorer l'efficacité de l'exécution du programme.

Après avoir terminé les étapes ci-dessus, les fonctions et les données de la bibliothèque statique seront intégrées dans le fichier exécutable final. Le fichier exécutable généré ne dépend pas de fichiers de bibliothèques externes, il peut donc être exécuté dans un environnement sans bibliothèques statiques.

Le processus d'utilisation d'une bibliothèque statique L'
utilisation d'une bibliothèque statique comprend le processus de création d'une bibliothèque statique, de liaison de la bibliothèque statique au programme et d'exécution du programme. Voici les étapes détaillées :

  1. Écrire le code source des fonctions de bibliothèque : écrivez des fichiers de code source contenant des fonctions et des variables couramment utilisées, telles que des fichiers .c ou .cpp.
  2. Écrire un fichier d'en-tête : créez un fichier d'en-tête, tel qu'un fichier .h ou .hpp, pour la fonction de bibliothèque. Ce fichier doit contenir des prototypes de fonctions et des déclarations de variables globales pour les fonctions de bibliothèque.
  3. Compiler le code source de la fonction de bibliothèque : compilez les fichiers de code source en fichiers objets (par exemple, des fichiers .o ou .obj). Sur les systèmes de type Unix, vous pouvez utiliser le compilateur gcc ou g++. Sur les systèmes Windows, le compilateur cl peut être utilisé.
    Exemple (système de type Unix) :
gcc -c example.c -o example.o
  1. Créez une bibliothèque statique : regroupez le fichier cible dans un fichier de bibliothèque statique. Sur les systèmes de type Unix, utilisez la commande ar pour créer le fichier .a. Sur les systèmes Windows, utilisez la commande lib pour créer le fichier .lib.
    Exemple (système de type Unix) :
ar rcs libexample.a example.o
  1. Écriture du code source du programme : écrivez un programme qui utilisera des fonctions et des variables d'une bibliothèque statique. Incluez les fichiers d'en-tête de la bibliothèque dans le code source.
    Exemple (système de type Unix) :
#include "example.h"

int main() {
    example_function();
    return 0;
}
  1. Compilez et liez le programme : Compilez le code source du programme dans un fichier objet et liez-le à l'aide d'une bibliothèque statique. Pendant le processus de compilation et de liaison, spécifiez le chemin et le nom de la bibliothèque statique afin que le compilateur et l'éditeur de liens puissent trouver et lier les fichiers de bibliothèque.
    Exemple (système de type Unix) :
gcc main.c -o main -L. -lexample

Dans cet exemple, -L. spécifie le chemin de recherche des fichiers de bibliothèque (le répertoire actuel) et -lexample spécifie le nom de la bibliothèque vers laquelle créer un lien (libexample.a).
7. Exécutez le programme : Le fichier exécutable contient désormais toutes les fonctions et données nécessaires de la bibliothèque statique. Lors de l'exécution du programme, il n'est pas nécessaire de recourir à des fichiers de bibliothèque externes.
Exemple (système de type Unix) :

./main

Grâce aux étapes ci-dessus, la bibliothèque statique est liée avec succès au programme et le programme est exécuté. Notez que si vous modifiez des fonctions ou des données dans la bibliothèque, vous devrez recompiler la bibliothèque et la lier à votre programme pour que les mises à jour prennent effet.

Bibliothèque de liens partagée

Une bibliothèque de liens partagés (également appelée bibliothèque de liens dynamiques) est un moyen de regrouper des fichiers objets compilés dans un fichier de bibliothèque. Contrairement aux bibliothèques de liens statiques, les bibliothèques de liens partagées sont chargées et liées dynamiquement lorsque le programme est en cours d'exécution, ce qui signifie que le programme n'a pas besoin d'intégrer les fonctions et les données de la bibliothèque dans le fichier exécutable. Les bibliothèques de liens partagées peuvent être partagées par plusieurs programmes, réduisant ainsi la taille du programme et économisant de la mémoire.

Dans les systèmes de type Unix (tels que Linux), les bibliothèques de liens partagés ont généralement .so (représentant « objet partagé ») comme extension de fichier, comme libexample.so. Dans les systèmes Windows, les bibliothèques de liens partagés portent généralement l'extension de fichier .dll (qui signifie « bibliothèque de liens dynamiques »).

Les étapes générales pour créer une bibliothèque de liens partagée sont les suivantes :

  • Écrivez des fichiers de code source (par exemple .c, .cpp) et implémentez les fonctions et les données requises.
  • Utilisez les options du compilateur pour compiler les fichiers de code source dans des fichiers de bibliothèque de liens partagés. Par exemple, sur un système de type Unix utilisant le compilateur gcc ou g++, vous pouvez utiliser l'option -shared pour créer une bibliothèque de liens partagée.
    Exemple (système de type Unix) :
gcc -shared -fPIC example.c -o libexample.so

Dans cet exemple, l'option -fPIC demande au compilateur de générer du code indépendant de la position, requis pour créer des bibliothèques partagées.

Les étapes générales d'utilisation des bibliothèques de liens partagées sont les suivantes

  • Incluez dans le code source les déclarations (généralement dans les fichiers d'en-tête) des fonctions et des données de la bibliothèque partagée.
  • Pendant le processus de compilation et de liaison, spécifiez le chemin et le nom de la bibliothèque de liens partagée afin que le compilateur et l'éditeur de liens puissent trouver et lier les fichiers de bibliothèque.
    Exemple (système de type Unix) :
gcc main.c -o main -L. -lexample

Dans cet exemple, -L. spécifie le chemin de recherche des fichiers de bibliothèque (le répertoire actuel) et -lexample spécifie le nom de la bibliothèque vers laquelle créer un lien (libexample.so).

  • Assurez-vous que la bibliothèque partagée est disponible au moment de l'exécution. Le système d'exploitation doit être capable de trouver les fichiers de bibliothèque partagés dans des chemins de recherche prédéfinis. Vous pouvez installer les fichiers de bibliothèque de liens partagés dans le répertoire de bibliothèque système ou spécifier l'emplacement des fichiers de bibliothèque en définissant des variables d'environnement (telles que LD_LIBRARY_PATH).

Avantages des bibliothèques de liens partagées :

  • Peut être partagé par plusieurs programmes, économisant ainsi de l'espace disque et de la mémoire.
  • Lorsque vous mettez à jour une bibliothèque, vous remplacez simplement les fichiers de la bibliothèque sans recompiler ni lier les programmes qui utilisent la bibliothèque.

Inconvénients des bibliothèques de liens partagées :

  • Les bibliothèques de liens partagées doivent être chargées et liées au moment de l'exécution, ce qui peut entraîner des problèmes de dépendance et de compatibilité des versions.
  • Les programmes doivent s'appuyer sur des fichiers de bibliothèque externes lors de leur exécution, ce qui peut compliquer le déploiement et la distribution.

En résumé, les bibliothèques partagées conviennent à ceux qui souhaitent économiser.

Processus de chargement de lien dynamique :
le processus de chargement de lien dynamique est le processus de chargement de bibliothèques partagées (bibliothèques de liens dynamiques) en mémoire et de leur liaison lorsque le programme est en cours d'exécution. Cette méthode de chargement permet à plusieurs programmes de partager le même code et les mêmes données de bibliothèque, économisant ainsi de la mémoire et de l'espace disque. Voici un aperçu du processus de chargement de la liaison dynamique :
1. Démarrage du programme : lorsque l'utilisateur tente d'exécuter un fichier exécutable, le système d'exploitation charge le programme en mémoire. L'en-tête du fichier exécutable contient des informations sur les bibliothèques partagées dont dépend le programme.
2. Charger les bibliothèques partagées : pendant le processus de démarrage du programme, l'éditeur de liens dynamique (généralement ld.so ou ld-linux.so dans les systèmes de type Unix, ntdll.dll dans les systèmes Windows) est responsable de la recherche et du chargement des programmes que le programme dépend de la bibliothèque partagée. L'éditeur de liens dynamique recherche les chemins de recherche prédéfinis du système d'exploitation (tels que /lib, /usr/lib, etc.) et les chemins spécifiés par les variables d'environnement (telles que LD_LIBRARY_PATH) pour trouver les fichiers de bibliothèque partagés requis.
3. Lier les bibliothèques partagées : L'éditeur de liens dynamique associe les adresses de symboles (telles que les fonctions et les variables) dans les bibliothèques partagées avec les références de symboles dans le programme. De cette manière, le programme peut appeler des fonctions dans la bibliothèque partagée et accéder aux données de la bibliothèque partagée. Dans les systèmes de type Unix, le processus de lien symbolique est généralement implémenté à l'aide de la table de décalage global (GOT) et de la table de liaison de procédure (PLT).
4. Relocalisation : l'éditeur de liens dynamique traite les informations de relocalisation dans la bibliothèque partagée pour corriger la référence à l'adresse de la bibliothèque partagée dans le programme. Cela peut inclure la mise à jour d'une instruction d'appel de fonction vers l'adresse cible correcte ou la mise à jour d'une référence de variable globale vers l'emplacement mémoire correct.
5. Initialisez la bibliothèque partagée : L'éditeur de liens dynamique appellera la fonction d'initialisation (le cas échéant) dans la bibliothèque partagée pour terminer l'initialisation de la bibliothèque. Ces fonctions d'initialisation peuvent inclure l'allocation de mémoire, la définition de variables globales, etc.
6. Programme en cours d'exécution : une fois la bibliothèque partagée chargée et liée, le programme commence à s'exécuter. À ce stade, le programme peut appeler des fonctions dans la bibliothèque partagée et accéder aux données de la bibliothèque partagée. Si le programme nécessite davantage de bibliothèques partagées pendant son fonctionnement, l'éditeur de liens dynamique peut également charger et lier ces bibliothèques selon les besoins (c'est ce qu'on appelle le chargement différé ou le chargement à la demande).
7. Libérer les bibliothèques partagées : lorsque l'exécution du programme est terminée et se termine, l'éditeur de liens dynamique déchargera les bibliothèques partagées et libérera les ressources associées. Cela peut inclure l'appel du destructeur dans la bibliothèque partagée (s'il y en a une) et la libération de la mémoire.

Liaison dynamique au moment de l'exécution La
liaison dynamique au moment de l'exécution fait référence au processus de chargement et de liaison des bibliothèques partagées (bibliothèques de liens dynamiques) selon les besoins pendant l'exécution du programme. Cette méthode de liaison permet au programme de charger et décharger des bibliothèques partagées à la demande au moment de l'exécution, économisant ainsi des ressources et augmentant la flexibilité. La liaison dynamique au moment de l'exécution repose principalement sur la fonction de liaison dynamique fournie par le système d'exploitation.

Dans les systèmes de type Unix (tels que Linux), la liaison dynamique d'exécution est généralement implémentée via les fonctions dlopen, dlsym, dlclose et dlerror. Dans les systèmes Windows, la liaison dynamique d'exécution est généralement implémentée via des fonctions telles que LoadLibrary, GetProcAddress et FreeLibrary.

おすすめ

転載: blog.csdn.net/m0_56898461/article/details/129790271