๐ Retour au Sommaire
Quand vous compilez un programme C composรฉ de plusieurs fichiers, comment le compilateur sait-il oรน se trouve la fonction printf ? Comment lโรฉditeur de liens connecte-t-il un appel de fonction dans un fichier ร sa dรฉfinition dans un autre ?
La rรฉponse rรฉside dans les symboles et la table des symboles.
Dans cette section, vous apprendrez :
Un symbole est un nom associรฉ ร une adresse mรฉmoire. Cโest la faรงon dont le compilateur et lโรฉditeur de liens identifient les รฉlรฉments de votre programme.
En termes simples :
Prenons ce programme simple :
// programme.c
#include <stdio.h>
int compteur = 0; // Symbole : compteur (variable globale)
void incrementer(void) { // Symbole : incrementer (fonction)
compteur++;
}
int main(void) { // Symbole : main (fonction)
incrementer();
printf("%d\n", compteur);
return 0;
}
Ce programme crรฉe 3 symboles :
compteur โ une variable globaleincrementer โ une fonctionmain โ la fonction principaleIl utilise รฉgalement un symbole externe :
printf โ dรฉfini dans la bibliothรจque CLes variables locales (automatiques) ne crรฉent pas de symboles :
void exemple(void) {
int variable_locale = 42; // PAS de symbole (variable locale)
for (int i = 0; i < 10; i++) { // PAS de symbole (i est local)
// ...
}
}
Les variables locales vivent sur la pile et nโont pas besoin de symboles car elles ne sont pas accessibles depuis dโautres fichiers.
Attention : Les variables
staticlocales ร une fonction (static int compteur = 0;) sont un cas particulier. Elles crรฉent un symbole local (visible avecnmsous la formed compteur.1234) car elles sont stockรฉes dans.dataou.bss, pas sur la pile. Cependant, ce symbole nโest pas exportรฉ et nโintervient pas dans lโรฉdition de liens entre fichiers.
La table des symboles est une structure de donnรฉes contenue dans les fichiers objets (.o) et les exรฉcutables. Elle liste tous les symboles avec leurs informations :
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ TABLE DES SYMBOLES DE programme.o โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Nom Adresse Type Taille Section Visibilitรฉ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ compteur 0x00000000 OBJECT 4 .data GLOBAL โ
โ incrementer 0x00000000 FUNC 23 .text GLOBAL โ
โ main 0x00000017 FUNC 45 .text GLOBAL โ
โ printf (externe) FUNC ? ? UNDEFINED โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Lรฉgende : โ
โ โข OBJECT = variable (donnรฉes) โ
โ โข FUNC = fonction (code) โ
โ โข GLOBAL = visible depuis d'autres fichiers โ
โ โข UNDEFINED = utilisรฉ mais non dรฉfini ici (sera rรฉsolu au linkage) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Lโoutil nm affiche la table des symboles :
gcc -c programme.c -o programme.o
nm programme.o
Rรฉsultat :
0000000000000000 D compteur
0000000000000000 T incrementer
0000000000000017 T main
U printf
Lโoutil readelf donne plus de dรฉtails :
readelf -s programme.o
Rรฉsultat (simplifiรฉ) :
Symbol table '.symtab' contains 12 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS programme.c
...
8: 0000000000000000 4 OBJECT GLOBAL DEFAULT 3 compteur
9: 0000000000000000 23 FUNC GLOBAL DEFAULT 1 incrementer
10: 0000000000000017 45 FUNC GLOBAL DEFAULT 1 main
11: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND printf
nmLโoutil nm utilise des lettres pour identifier le type de chaque symbole :
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ TYPES DE SYMBOLES (nm) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ LETTRE SECTION DESCRIPTION โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโ CODE (FONCTIONS) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โ T .text Fonction dรฉfinie, GLOBALE (visible) โ โ
โ โ t .text Fonction dรฉfinie, locale (static) โ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโ DONNรES INITIALISรES โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โ D .data Variable initialisรฉe, GLOBALE โ โ
โ โ d .data Variable initialisรฉe, locale (static) โ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโ DONNรES NON INITIALISรES โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โ B .bss Variable non initialisรฉe, GLOBALE โ โ
โ โ b .bss Variable non initialisรฉe, locale โ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโ DONNรES EN LECTURE SEULE โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โ R .rodata Constante, GLOBALE โ โ
โ โ r .rodata Constante, locale โ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโ SYMBOLES SPรCIAUX โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โ U (aucune) UNDEFINED - Non dรฉfini, ร rรฉsoudre โ โ
โ โ C (common) Variable "commune" (GCC < 10, -fcommon) โ โ
โ โ W / w (weak) Symbole faible (peut รชtre remplacรฉ) โ โ
โ โ A (absolute) Adresse absolue (ne change pas) โ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Note : Majuscule = GLOBAL (visible), Minuscule = local (non visible) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// types_symboles.c
#include <stdio.h>
// Variables globales
int var_init = 42; // D - data, initialisรฉe
int var_non_init; // B - bss, non initialisรฉe
const int constante = 100; // R - rodata, lecture seule
// Variables statiques (locales au fichier)
static int var_static = 10; // d - data, locale
static void helper(void) { } // t - text, locale
// Fonction globale
void publique(void) { // T - text, globale
printf("Hello\n"); // U - undefined (externe)
}
int main(void) { // T - text, globale
return 0;
}
gcc -c types_symboles.c -o types_symboles.o
nm types_symboles.o
Rรฉsultat :
0000000000000000 t helper
0000000000000000 T main
U printf
0000000000000000 T publique
0000000000000000 R constante
0000000000000000 D var_init
0000000000000004 B var_non_init
0000000000000004 d var_static
Un symbole est dรฉfini quand le code ou les donnรฉes correspondantes existent dans ce fichier :
// Dans fichier1.c
int ma_variable = 42; // Dรฉfinition โ symbole D
void ma_fonction(void) { // Dรฉfinition โ symbole T
// code
}
Un symbole est non dรฉfini (U) quand il est utilisรฉ mais pas dรฉfini dans ce fichier :
// Dans fichier2.c
extern int ma_variable; // Dรฉclaration (pas dรฉfinition) โ U
void autre_fonction(void) {
ma_fonction(); // Utilisation โ U (sera liรฉ plus tard)
printf("%d", ma_variable); // printf est U aussi
}
Cโest lโรฉditeur de liens qui rรฉsout les symboles non dรฉfinis :
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ RรSOLUTION DES SYMBOLES โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โ
โ fichier1.o fichier2.o โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ ma_variable : D โ โ ma_variable : U โโผโโโโ โ
โ โ ma_fonction : T โ โ ma_fonction : U โโผโโโโผโโโ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ autre_fonction : T โ โ โ โ
โ โ โ printf : U โโผโโโโผโโโผโโโ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโ โ โ โ โ
โ โ โ โ โ โ
โ โ libc.so โ โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโ โ โ โ โ
โ โ โ printf : T โโผโโโโโโโโโโโโโโโผโโโผโโโ โ
โ โ โ malloc : T โ โ โ โ
โ โ โ ... โ โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโ โ โ โ
โ โ โ โ โ
โ โ LINKER โ โ โ
โ โ โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ programme โ โ
โ โ (exรฉcutable) โ โ
โ โ โ โ
โ โ Tous les symboles โ โ
โ โ sont rรฉsolus ! โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Si lโรฉditeur de liens ne trouve pas un symbole, il affiche une erreur :
gcc fichier1.o fichier2.o -o programme
# undefined reference to `fonction_inexistante'
Cette erreur signifie quโun symbole U nโa trouvรฉ aucun symbole T ou D correspondant.
Par dรฉfaut, toutes les fonctions et variables globales sont visibles depuis les autres fichiers :
// module.c
int variable_publique = 42; // Visible partout
void fonction_publique(void) { // Visible partout
// ...
}
staticLe mot-clรฉ static rend un symbole local au fichier (non exportรฉ) :
// module.c
static int variable_privee = 42; // Invisible depuis l'extรฉrieur
static void fonction_privee(void) { // Invisible depuis l'extรฉrieur
// ...
}
void fonction_publique(void) { // Visible
fonction_privee(); // Peut รชtre appelรฉe ici
}
// fichier_a.c
int globale = 1; // nm: D globale (GLOBAL)
static int locale = 2; // nm: d locale (local)
void publique(void) { } // nm: T publique (GLOBAL)
static void privee(void) { } // nm: t privee (local)
nm fichier_a.o
0000000000000000 D globale
0000000000000004 d locale
0000000000000011 t privee
0000000000000000 T publique
externLe mot-clรฉ extern dรฉclare quโun symbole existe ailleurs :
// fichier_b.c
extern int globale; // Dรฉclare (ne dรฉfinit pas)
// extern int locale; // ERREUR : locale n'est pas exportรฉe !
void autre(void) {
globale = 100; // OK : globale est visible
}
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ VISIBILITร DES SYMBOLES โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ fichier_a.c fichier_b.c โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ โ โ
โ โ int globale = 1; โโโโโโผโโโโโโโโผโโโถ extern int globale; โ โ โ
โ โ (GLOBAL) โ โ โ โ
โ โ โ โ โ โ
โ โ static int locale = 2; โ โณ โ extern int locale; โ โ โ
โ โ (local) โ โ (ERREUR: invisible) โ โ
โ โ โ โ โ โ
โ โ void publique() { } โโโโโผโโโโโโโโผโโโถ publique(); โ โ โ
โ โ (GLOBAL) โ โ โ โ
โ โ โ โ โ โ
โ โ static void privee() { } โ โณ โ privee(); โ โ โ
โ โ (local) โ โ (ERREUR: invisible) โ โ
โ โ โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Rรจgle : static = privรฉ au fichier, visible uniquement dans ce fichier โ
โ (dรฉfaut) = public, visible par tous les fichiers โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Par dรฉfaut, les symboles sont forts. Un symbole fort ne peut รชtre dรฉfini quโune seule fois :
// fichier1.c
int valeur = 10; // Symbole fort
// fichier2.c
int valeur = 20; // Symbole fort โ ERREUR : dรฉfinition multiple !
gcc fichier1.c fichier2.c -o programme
# error: multiple definition of `valeur'
Un symbole faible peut รชtre remplacรฉ par un symbole fort :
// defaut.c
__attribute__((weak)) int config = 100; // Symbole faible
void afficher(void) {
printf("config = %d\n", config);
}
// personnalise.c
int config = 200; // Symbole fort, remplace le faible
gcc defaut.c personnalise.c -o programme
./programme
# config = 200 (le symbole fort a gagnรฉ)
Les symboles faibles sont utiles pour :
// bibliotheque.c
// Fonction par dรฉfaut (peut รชtre remplacรฉe)
__attribute__((weak)) void on_error(int code) {
fprintf(stderr, "Erreur %d\n", code);
}
void faire_quelque_chose(void) {
if (/* erreur */) {
on_error(42); // Appelle la version de l'utilisateur si elle existe
}
}
// application.c
// L'utilisateur fournit sa propre implรฉmentation
void on_error(int code) {
log_to_file("Erreur", code);
send_alert(code);
}
nm fichier.o | grep -i weak
# w ou W indique un symbole faible
Les symboles sont associรฉs ร des sections dans le fichier objet :
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SECTIONS ET SYMBOLES โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ SECTION CONTENU SYMBOLES ASSOCIรS โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ .text Code exรฉcutable Fonctions (T/t) โ
โ Instructions machine main, printf, helper... โ
โ โ
โ .data Variables initialisรฉes Variables globales (D/d) โ
โ int x = 42; var_init, var_static... โ
โ โ
โ .bss Variables non initialisรฉes Variables globales (B/b) โ
โ int y; var_non_init... โ
โ (rempli de zรฉros au runtime) โ
โ โ
โ .rodata Donnรฉes en lecture seule Constantes (R/r) โ
โ const int c = 10; constante, chaรฎnes... โ
โ "Hello World" โ
โ โ
โ .symtab Table des symboles (mรฉtadonnรฉes) โ
โ Noms, adresses, types โ
โ โ
โ .strtab Table des chaรฎnes (noms des symboles) โ
โ "main", "printf", etc. โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
readelf -S programme.o | grep -E "\.text|\.data|\.bss|\.rodata"
# Voir les symboles avec leur section
nm -o programme.o
# Ou avec readelf
readelf -s programme.o
La colonne Ndx (index) indique la section :
1 = .text3 = .dataUND = non dรฉfiniLors de lโรฉdition de liens, le linker :
// main.c
extern void afficher(void);
int compteur = 0;
int main(void) {
afficher();
return 0;
}
// affichage.c
#include <stdio.h>
extern int compteur;
void afficher(void) {
printf("Compteur: %d\n", compteur);
}
Symboles de main.o :
0000000000000000 D compteur (dรฉfini)
0000000000000000 T main (dรฉfini)
U afficher (non dรฉfini โ cherche ailleurs)
Symboles de affichage.o :
0000000000000000 T afficher (dรฉfini)
U compteur (non dรฉfini โ cherche ailleurs)
U printf (non dรฉfini โ cherche ailleurs)
Rรฉsolution :
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ RรSOLUTION โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Symbole main.o affichage.o libc.so Rรฉsultat โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ compteur D (dรฉfinit) U (cherche) โโโโโโโโโโโโโโโโโโ OK (main.o) โ
โ main T (dรฉfinit) - - OK (main.o) โ
โ afficher U (cherche) โโโถ T (dรฉfinit) - OK (affichage.o) โ
โ printf - U (cherche) โโโโโถ T (dรฉfinit) OK (libc.so) โ
โ โ
โ Tous les U sont rรฉsolus โ รdition de liens rรฉussie ! โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Les symboles occupent de lโespace et rรฉvรจlent des informations sur votre code :
# Avec l'outil strip
strip programme
# Ou lors de la compilation
gcc -s programme.c -o programme
# Compiler normalement
gcc programme.c -o programme_normal
ls -l programme_normal
# -rwxr-xr-x 1 user user 16696 ... programme_normal
# Compiler et stripper
gcc -s programme.c -o programme_stripped
ls -l programme_stripped
# -rwxr-xr-x 1 user user 14472 ... programme_stripped
# Voir les symboles
nm programme_normal | wc -l
# 35
nm programme_stripped
# nm: programme_stripped: no symbols
Pour la production, vous pouvez :
# Compiler avec symboles de debug
gcc -g programme.c -o programme_debug
# Crรฉer une version strippรฉe pour la distribution
cp programme_debug programme_release
strip programme_release
Vous pouvez aussi extraire les symboles dans un fichier sรฉparรฉ :
# Extraire les symboles de debug
objcopy --only-keep-debug programme programme.debug
# Stripper l'exรฉcutable
strip programme
# Lier les deux (pour GDB)
objcopy --add-gnu-debuglink=programme.debug programme
Cause : Un symbole utilisรฉ (U) nโest dรฉfini nulle part.
gcc main.o -o programme
# undefined reference to `ma_fonction'
Solutions :
.o contenant la dรฉfinition-lm, -pthread, etc.)# Trouver qui dรฉfinit le symbole
nm *.o | grep "ma_fonction"
Cause : Un symbole est dรฉfini plusieurs fois.
gcc fichier1.o fichier2.o -o programme
# multiple definition of `variable'
Solutions :
static pour les symboles qui doivent รชtre privรฉsextern pour dรฉclarer (pas dรฉfinir)// MAUVAIS (dans un .h inclus plusieurs fois)
int variable = 0; // Dรฉfinition !
// BON (dans un .h)
extern int variable; // Dรฉclaration seulement
// BON (dans UN SEUL .c)
int variable = 0; // Dรฉfinition unique
Cause : Une adresse est trop grande pour le format utilisรฉ.
Solutions :
-mcmodel=large)Cause : Bibliothรจque dynamique manquante.
./programme
# error while loading shared libraries: libxxx.so: cannot open shared object file
Solutions :
# Vรฉrifier les dรฉpendances
ldd programme
# Ajouter le chemin de la bibliothรจque
export LD_LIBRARY_PATH=/chemin/vers/lib:$LD_LIBRARY_PATH
| Outil | Usage | Exemple |
|---|---|---|
nm |
Lister les symboles | nm fichier.o |
nm -u |
Symboles non dรฉfinis uniquement | nm -u fichier.o |
nm -g |
Symboles globaux uniquement | nm -g fichier.o |
nm -C |
Dรฉmangler les noms C++ | nm -C fichier.o |
readelf -s |
Table des symboles dรฉtaillรฉe | readelf -s fichier.o |
objdump -t |
Table des symboles | objdump -t fichier.o |
objdump -T |
Symboles dynamiques | objdump -T programme |
ldd |
Bibliothรจques dynamiques | ldd programme |
# Trouver tous les fichiers dรฉfinissant un symbole
nm *.o | grep " T ma_fonction"
# Trouver tous les fichiers utilisant un symbole
nm *.o | grep " U ma_fonction"
# Voir les symboles exportรฉs d'une bibliothรจque
nm -D /lib/x86_64-linux-gnu/libc.so.6 | grep printf
# Comparer les symboles de deux fichiers
diff <(nm fichier1.o) <(nm fichier2.o)
static pour les Symboles Internes// module.c
static int etat_interne = 0; // Pas visible ร l'extรฉrieur
static void fonction_interne(void) {} // Pas visible ร l'extรฉrieur
void api_publique(void) { // Interface publique
fonction_interne();
}
// module.h
extern int variable; // Dรฉclaration
void fonction(void); // Dรฉclaration
// module.c
#include "module.h"
int variable = 42; // Dรฉfinition
void fonction(void) { /* ... */ } // Dรฉfinition
// module.h
#ifndef MODULE_H
#define MODULE_H
extern int variable;
void fonction(void);
#endif // MODULE_H
// MAUVAIS
int compteur_global = 0;
// MIEUX
static int compteur = 0;
int get_compteur(void) { return compteur; }
void increment_compteur(void) { compteur++; }
Les symboles sont le ciment qui lie les diffรฉrentes parties de votre programme :
static contrรดle la visibilitรฉ des symbolesCommandes essentielles ร retenir :
# Lister les symboles
nm fichier.o
# Symboles non dรฉfinis (ร rรฉsoudre)
nm -u fichier.o
# Table des symboles dรฉtaillรฉe
readelf -s fichier.o
# Bibliothรจques dynamiques
ldd programme
# Stripper les symboles
strip programme
Comprendre les symboles vous permet de diagnostiquer les erreurs de linkage, dโorganiser votre code en modules, et de crรฉer des bibliothรจques propres. Cโest une compรฉtence fondamentale pour tout dรฉveloppeur C travaillant sur des projets multi-fichiers.