先看一个内存问题:
(gdb) bt full
#0 0x080485e1 in main () at test1.c:12
handle = 0x8bcc018
p = 0xb7726014
(gdb) p *p
Cannot access memory at address 0xb7726014
(gdb) info proc mappings
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x8048000 0x8049000 0x1000 0x0 /home/charles/tmp/test1
0x8049000 0x804a000 0x1000 0x0 /home/charles/tmp/test1
0x804a000 0x804b000 0x1000 0x1000 /home/charles/tmp/test1
0xb7544000 0xb76f4000 0x1b0000 0x0 /lib/i386-linux-gnu/libc-2.23.so
0xb76f4000 0xb76f5000 0x1000 0x1b0000 /lib/i386-linux-gnu/libc-2.23.so
0xb76f5000 0xb76f7000 0x2000 0x1b0000 /lib/i386-linux-gnu/libc-2.23.so
0xb76f7000 0xb76f8000 0x1000 0x1b2000 /lib/i386-linux-gnu/libc-2.23.so
0xb76fb000 0xb76fe000 0x3000 0x0 /lib/i386-linux-gnu/libdl-2.23.so
0xb76fe000 0xb76ff000 0x1000 0x2000 /lib/i386-linux-gnu/libdl-2.23.so
0xb76ff000 0xb7700000 0x1000 0x3000 /lib/i386-linux-gnu/libdl-2.23.so
0xb772b000 0xb774e000 0x23000 0x0 /lib/i386-linux-gnu/ld-2.23.so
0xb774e000 0xb774f000 0x1000 0x22000 /lib/i386-linux-gnu/ld-2.23.so
(gdb)
可以看出,p指向的地址在进程的内存映射里面是找不到的。
一个可能的原因是,p的地址对应的模块已经从 进程里面 unload了,但是其它地方还在使用。
有问题的代码如下:
$ cat 1.c
#include <stdio.h>
int g_a = 200;
void foo(void)
{
printf("g_a = %d\n", g_a);
}
$ cat test1.c
#include <dlfcn.h>
#include <stdio.h>
int main(void)
{
int *handle = dlopen("./lib1.so", RTLD_LAZY);
int *p = dlsym(handle, "g_a");
printf("p = %d\n", *p);
printf("p = %x\n", p);
dlclose(handle);
*p =0;
return 0;
}
gcc 1.c -shared -fpic -g -o lib1.so
gcc test1.c -L. -l1 -ldl -o test1 -g
可以用gdb调试看一下 dlclose前后进程的内存映射就会明白。