Using special compiler commands a symbol can be declared weak. According to Wikipedia:
a weak symbol is a symbol definition in an object file or dynamic library that may be overridden by other symbol definitions
In what scenarios or for what applications do you need weak symbols? What are typical use cases?
Definition of weak link : the least strong or successful part the weak link in the company's line of products.
This behavior allows an executable to override standard library functions, such as malloc(3). When linking a binary executable, a weakly declared symbol does not need a definition. In comparison, (by default) a declared strong symbol without a definition triggers an undefined symbol link error.
In embedded development, when you have for instance a vector of interrupt pointers, it's very handy to be able to use weak linking to get default handlers for interrupts you're not interested in.
This works by defining an empty handler (once), then introducing one new properly-named symbol for each interrupt pointer that you need, which is weakly linked to the default handler.
The vector is then filled with these symbols, which will all point at the same actual code, until you decide to implement one of them using the same (proper) name, then your code "overpowers" the weak link, causing a pointer to your code to be installed in the interrupt table.
This is often implemented in some mixture of C and assembly, but using C pseudocode we might have something like:
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. */
Then you can just implement your own function when needed:
void timer1_isr(void) { /* Handler ISR from timer1. */ }
without having to change anything else, it "just works". As long as your name is the one that the above "support code" expects, of course.
One use of weak linking is implementing the replaceable functions in the C++ standard. Namely:
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;
These are functions which must be provided by the implementation, but if a program implements them then the program's implementation replaces or overrides the implementation's version. This is easily implemented via weak linkage.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With