Strong And Weak Symbol
While I was writing my last article, I found a .weak
label in assembly program. According to http://downloads.ti.com/docs/esd/SPNU118/weak-symbols-sprui029023.html, it is the same as #pragma weak
in C/C++.
What is weak symbol
The definition of weak symbol in C and C++ is different:
- In C, any global variables that are uninitiated is an weak symbol.
- In C++, if you don’t declare it as a weak symbol, everything is strong symbol.
What properties does it have
Simply put, it allows functions or variables with the same name to be multiple defined in multiple files, as long as:
-
Only one strong symbol in the program.
-
If we have multiple weak symbols, the linker (depends on the implement of the linker) will choose the first linked weak symbol. This also means that the same name can be defined for different types, since the first one linked will actually be defined.
Consider we have such program:
// test.cpp
#pragma weak ijkkl
float ijkkl = 10000;
void printType(){
std::cout << typeid(ijkkl).name() << std::endl;
}
// main.cpp
#pragma weak ijkkl
using namespace std;
int ijkkl = 10;
extern void printType();
int main() {
cout << typeid(ijkkl).name() << endl;
printType();
}
What is the actual size of variable ijkkl
?
The answer is the size of float
(in 64 machine, size of float
is the same as size of int
, but you know what I mean), we can check it by checking the binary memory view of the program.
What is the output of this program?
The answer is i
indicate to int
, and then f
indicate to float
.
So in conclusion, if we have multiple weak definition of a variable, the actual size of it will depends on the first linked file, and for each file that contain this variable, they think the variable’s type and size is the same as the definition in their own file. In this case, because float and int are encoded in different way, the output will be unreadable, so I suggest trying not to cause such confusion.
For weak symbol function, the actual function in the memory depends on the first linked file, and for each file that contain this function, they think the return type (parameter type is not included, since that will trigger function overload) of the function is the same as the definition in their own file. Which means if you have different definition of a function in different files, you might be unable to obtain the return value correctly.
No matter what kind of weak symbol it is, if it is undefined (no strong symbol with the same name in the whole project), it will be set to 0, so we have below good example:
A useful example
// test.cpp
#include <iostream>
int printType(){
printf("Hello test\n");
return 1129387;
}
// main.cpp
#include <iostream>
using namespace std;
int printType();
int main() {
if (printType){
printType();
}
}
In main.cpp
, we test if printType
equal to 0, if there isn’t a strong definition for this function, it will be set to 0.