I was playing around with symbols and function pointers recently and noticed that though the following code runs fine:
#include <stdio.h>
int main(int argc, const char * argv[]) {
printf("%p\n",printf); // <--this line makes it work
int (*printfptr)(const char * restrict, ...);
printfptr = 0x1001fe910;
(*printfptr)("Hello world\n");
return 0;
}
This does not:
#include <stdio.h>
int main(int argc, const char * argv[]) {
// printf("%p\n",printf); // <-- commenting this out breaks it
int (*printfptr)(const char * restrict, ...);
printfptr = 0x1001fe910;
(*printfptr)("Hello world\n");
return 0;
}
(EXC_BAD_ACCESS)
How come dereferencing the exact same pointer causes issues when there is no reference to printf
in the code? Even this works fine:
#include <stdio.h>
int main(int argc, const char * argv[]) {
int (*printfptr)(const char * restrict, ...);
printfptr = 0x1001fe910;
(*printfptr)("Hello world\n");
return 0;
}
void *_ = printf; // <-- because of this
Why is this?
On shared objects (.so) the symbols are really resolved only at the moment of first use. By default the linker sets the option -z lazy
which tells:
When generating an executable or shared library, mark it to
tell the dynamic linker to defer function call resolution to
the point when the function is called (lazy binding), rather
than at load time. Lazy binding is the default.
You can change that behaviour by providing option -z now
.
man ld
for all gory details.
EDIT: Resolving a symbol is done with dynamic link API on POSIX systems. Functions dlsym()
, dlopen()
, dlclose()
and dlerror()
defined in <dlfcn.h>
. This edition added so that you can search for these names.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.