Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use weak symbols and weak references in C language

2025-04-02 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article will explain in detail how to use weak symbols and weak citations in C language. The editor thinks it is very practical, so I share it with you as a reference. I hope you can get something after reading this article.

Symbol redefinition error

In the process of coding, we often encounter errors of symbol redefinition. The compiler reports the following error:

Multiple definition of `xxx'

This is caused by the repeated definition of symbols, and in more detail, it is a conflict of symbols in the same scope. We know that variables are defined by scope and lifecycle. For example:

Example 1:main.cint strong=0;int main () {printf ("strong=% d\ n", strong); return 0;} strong.cint strong=1

Gcc main.c strong.c-o main will report a redefinition error. Because the integer variable strong is a global variable in main.c and strong.c files, their scope is cross-file. If in different scopes, the error will not be reported even if the variable name is the same. The compiler has a default priority treatment: variables with a smaller scope always override variables with a larger scope, as long as the scope of the two variables is an inclusive or included relationship. For example:

Example 2:main.cint strong=0;int main () {printf ("strong=% d\ n", strong); return 0;} strong.cstatic int strong=1

Gcc main.c strong.c-o main no longer reports an error. At this point, the scope of the strong variable in main.c is cross-file, while the scope of the strong variable in strong.c is limited to strong.c files. Therefore, there is no problem of symbol redefinition in the same scope. And the result output is 0

Similarly, will the following code compile and report an error? What is the output?

Main.cint strong=0;int main () {int strong=2; printf ("strong=% d\ n", strong); return 0;} strong.cstatic int strong=1

Even the following code is legal:

Main.cint strong=0;int main () {int strong=2; if (1) {int strong=3;} {int strong= 4; printf ("strong=% d\ n", strong);} return 0;}

In C language, we can simply think of curly braces as the delimiter of the scope within the file.

Strong symbols and weak symbols

The compiler default function and initialized global variables are strong symbols, while uninitialized global variables are weak symbols; at the same time, developers can declare a symbol as weak symbols through "attribute ((weak))"

In the process of compilation, gcc follows certain rules to choose between strong and weak symbols:

"redefinition of 'xxx'" error is reported when there are multiple strong symbols

When only one is a strong symbol, select the value of the strong symbol

When all are weak symbols, select the symbol with more temporary space. (preventing overflow crossing boundaries, etc.)-this should have something to do with the compiler. I do not allow multiple weak symbols of different types to exist in the local environment. Compilation can go wrong.

Obviously, example 1 is a redefinition error caused by multiple strong symbols. For example, the following code:

Main.cint strong;int strong=2;int main () {printf ("strong=% d\ n", strong); return 0;}

There is no error in the compilation, and the output is 2

Strong reference and weak reference

We know that when compiling to an executable file, if the source file references the symbol of the external target file, the corresponding symbol definition needs to be found in the link process. If the corresponding symbol is not found (undefined), the linker will report an undefined error in the symbol bit, resulting in a compilation error. This is called a strong reference. Corresponding to the weak reference (developers can declare through attribute ((weakref), if the linker finds that the symbol is a weak reference in the link symbol process, the link will not report an error even if the symbol definition is not found, but the reference will default to 0

The code in the book is as follows:

Main.cint strong;int strong=2;int main () {printf ("strong=% d\ n", strong); return 0;}

Although foo () is not defined, we can compile it into an executable file, and GCC compilation does not report link errors, but when we run it, a run error occurs. In fact, the new version of the compiler appeal code will be wrong in the link times, the new version of the sample code should be as follows: (the new version of weakref requires a function alias and must be static decorated)

Main.cstatic _ attribute__ ((weakref ("foo") void myfoo (void); void main (void) {if (myfoo) {myfoo ();}}

The new version of weak symbol references is shown above. This means that if the foo function is not found, the compiler will not report an error, but the default myfoo will be NULL. If the foo function is defined in other libraries, a reference to myfoo is equivalent to a reference to foo. This kind of weak reference is very useful in the use of libraries.

Bar

Through the above description, we have learned the concepts of strong symbol, weak symbol, strong reference and weak reference. I think there are at least two features that can be used in our work:

Strong symbols can replace weak symbols.

Weak references can avoid errors that are not defined by the function.

Strong symbols replace weak symbols

External interfaces in some libraries can be declared as weak symbols. For example:

In the math library, we find that there is a problem with the interface add (int num1, int num2), so we generally have the following solutions:

1. Implement a myadd (int num1,int num2) interface, and then replace all add in the project with myadd. This approach is feasible, but there are disadvantages: a large amount of modification, and the follow-up staff is not clear about the background, it is likely to continue to use the familiar add interface.

two。 Update the math library to resolve this issue from the update. This method is more recommended. But it is not generic, for example, some libraries are not open source and have passed the support date, so they are not applicable.

At this point, we can define an add (int num1,int num2) interface in the project and replace the weak symbols in the library with strong symbols, which is relatively minor. (this scenario requires understanding the implementation of the interface, which gives the caller higher refactoring power.)

Skillfully using weak references to improve the robustness of code

The development of the application layer is inseparable from the provision of sdk. Generally, sdk is maintained. Even if the application has no requirements, it will often make simple modifications in order to cooperate with sdk. Take equipment upgrade as an example, if the upgrade process is divided into pass, verify, decode, install, report and other steps, and these core interfaces are provided to application engineers in the form of libsdk.so library. Under normal circumstances, the application logic is roughly as follows:

User business processes... pass ();... verify ();... decode ();... install ();... report ();...

But this kind of business code, I think is very bad. For example, in a new project, there is no need to decrypt the package (theoretically, there should be no decode interface in the libsdk.so library), which will cause the application to fail to compile. Undefine 'decode'.

Therefore, I suggest that the application code can be as follows:

Static _ attribute__ ((weakref ("pass")) void mypass (void); static _ attribute__ ((weakref ("verify") void myverify (void); static _ attribute__ ((weakref ("decode")) void mydecode (void); static _ attribute__ ((weakref ("install")) void myinstall (void); static _ attribute__ ((weakref ("report")) void myreport (void); user business process. If (mypass) mypass () Else printf ("don't need pass\ n");... if (myverify) myverify (); else printf ("don't need verify\ n");... if (mydecode) mydecode (); else printf ("don't need decode\ n");... if (myinstall) myinstall (); else printf ("don't need install\ n");... if (myreport) myreport () Else printf ("don't need report\ n");... This is the end of the article on "how to use weak symbols and weak citations in C language". I hope the above content can be helpful to you, so that you can learn more knowledge. If you think the article is good, please share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report