2013-03-20 147 views
19

Utilizzando i comandi speciali del compilatore, è possibile dichiarare un simbolo debole. According to Wikipedia:Quali sono le applicazioni pratiche del collegamento debole?

un simbolo debole è una definizione simbolo in un file oggetto o una libreria dinamica che può essere annullato con altro simbolo definizioni

In quali scenari o per quali applicazioni avete bisogno simboli deboli? Quali sono i tipici casi d'uso?

+1

https://ofekshilon.com/2014/02/10/linker-weak-symbols/ –

risposta

15

Un uso di collegamento debole attua le sostituibili funzioni nel Standard C++. Vale a dire:

void *operator new(std::size_t); 
void *operator new(std::size_t, std::nothrow_t const &) noexcept; 
void *operator new[](std::size_t); 
void *operator new[](std::size_t, const std::nothrow_t&) noexcept; 
void operator delete(void *) noexcept; 
void operator delete(void *, std::nothrow_t const &) noexcept; 
void operator delete[](void *) noexcept; 
void operator delete[](void *, std::nothrow_t const &) noexcept; 

Si tratta di funzioni che devono essere forniti in sede di attuazione, ma se un programma li implementa poi l'attuazione del programma sostituisce o sovrascrive la versione del implementazione. Questo è facilmente implementabile tramite un debole collegamento.

+0

@BernhardKausler fornisce alcune domande SO correlate che potrebbero fornire ulteriori informazioni: [Perché si dovrebbero sostituire i nuovi operatori di default ed eliminare?] (http://stackoverflow.com/questions/7149461/why-would-one -replace-default-new-and-delete-operators) [Come sostituire correttamente gli operatori globali nuovi e di eliminazione] (http://stackoverflow.com/questions/8186018/how-to-properly-replace-global-new-delete -operatori) [Come dovrei scrivere uno standard conforme ISO C++ e cancellare gli operatori?] (http://stackoverflow.com/questions/7194127/how-should-i-write-iso-c-standard-conformant-custom- nuovo e gli operatori-delete-) – bames53

15

In sviluppo embedded, quando si ha per esempio un vettore di puntatori di interruzione, è molto utile per essere in grado di utilizzare il collegamento debole per ottenere gestori predefiniti per gli interrupt che non sei interessato a.

Questo funziona definendo un gestore vuoto (una sola volta), quindi introducendo un nuovo simbolo opportunamente nominato per ogni puntatore di interrupt di cui hai bisogno, che è debolmente collegato al gestore predefinito.

Il vettore viene quindi riempito con questi simboli, che puntano tutti allo stesso codice effettivo, finché non si decide di implementare uno di essi utilizzando lo stesso nome (corretto), quindi il codice "soprapassa" il collegamento debole, causando un puntatore al codice da installare nella tabella degli interrupt.

questo è spesso implementato in un misto di C e di assemblaggio, ma utilizzando C pseudocodice potremmo avere qualcosa di simile:

static void placeholder_isr(void) 
{ 
} 

/* Introduce properly-named function pointers, with weak linking. 
* NOTE: This syntax is completely fictional as far as I know. 
*/ 
void (*timer1_isr)() = placeholder_isr __attribute("weak linking"); 
void (*timer2_isr)() = placeholder_isr __attribute("weak linking"); 
void (*usart1_isr)() = placeholder_isr __attribute("weak linking"); 
void (*usart2_isr)() = placeholder_isr __attribute("weak linking"); 
void (*dma1_isr)() = placeholder_isr __attribute("weak linking"); 
void (*dma1_isr)() = placeholder_isr __attribute("weak linking"); 

/* Declare the table of interrupt handlers. */ 
static void (*isr_table)[] = { 
    timer1_isr, 
    timer2_isr, 
    usart1_isr, 
    usart2_isr, 
    dma1_isr, 
    dma2_isr, 
} __attribute("isr vector"); /* Attribute to place it where it needs to go. */ 

Poi si può solo implementare la propria funzione in caso di necessità:

void timer1_isr(void) 
{ 
    /* Handler ISR from timer1. */ 
} 

senza dover cambiare altro, "funziona". Finché il tuo nome è quello che il "codice di supporto" di cui sopra si aspetta, ovviamente.

5

The weak attributo provoca la dichiarazione venga emessa come un debole simbolo piuttosto che un globale. Ciò è utile soprattutto nella definizione delle funzioni della libreria che possono essere sovrascritte nel codice utente, sebbene sia possibile utilizzare anche con le dichiarazioni senza funzione. I simboli deboli sono supportati per i target ELF e anche per gli obiettivi a.out quando si utilizza l'assemblatore e il linker GNU .

The weak attribute example:

weak.c

extern void foo() __attribute__((weak)); 

int main() { 
if (foo) foo(); 
} 

foo.c

void foo() { 
printf("in foo.\n"); 
} 

forte.c

extern void foo() ; 

int main() { 
if (foo) foo(); 
} 

compilazione

$ cc weak.c // Compiles OK 
$ cc strong.c // undefined reference to `foo' 

Quando il "foo" è dichiarata essere debole, la sua definizione può essere omesso, o sostituiti da diverse librerie, con gentile di "link-time vincolante". Il linker riempirà 0 per i simboli deboli indefiniti.

2

Generalmente si utilizza il collegamento debole quando si desidera poter eseguire l'override di una definizione di funzione in un'altra parte del codice. Questo è tipicamente il caso nelle biblioteche che specificano ad es. un gestore di errori predefinito che è possibile sovrascrivere con una funzione personalizzata se si utilizza la libreria.

4

Il caso di utilizzo tipico e giornaliero è rappresentato dalle funzioni inline e modello.

Ad esempio questa parte del codice se compilato con g++ -shared -fPIC:

extern void a(); 

inline void foo() { a(); } 

void bar() { foo(); } 
void baz() { foo(); } 

sarebbe simboli bar e baz contrassegnati come T (normale) di nm e Foo verrà contrassegnata come W - debole.

(cioè mn -C ./a.out)

Rationale:

funzioni in linea e modelli possono essere definiti nelle intestazioni e solitamente definiti più volte in diverse parti di fonti e infine un solo rimane attiva.

Se non sarebbe stato contrassegnato come Debole sarebbe collisione di simboli multipli "foo" o il compilatore non sarebbe in grado di disattivare inlining

+0

E, pertanto, anche la maggior parte delle funzioni del modello sarà debole. –

+0

@MatthieuM. infatti, aggiunto alla risposta – Artyom

Problemi correlati