У меня есть две реализации одного и того же поведения, которые, я считаю, должны давать одинаковые результаты, но вместо этого дают разные результаты.При компиляции в Go с использованием cgo
я получаю другое разрешение адреса символа, чем при компиляции в C. Я хотел бы понять, почему.
Я сократил проблему до пары небольших примеров, один на C иодин на ходу.Я протестировал их в контейнере Ubuntu 18 Docker, работающем на моем ноутбуке Mac.
test.c:
// gcc test.c -D_GNU_SOURCE -ldl
// Output: Real: 0x7fd05559d7d0 Current: 0x7fd05559d7d0
#include <dlfcn.h>
#include <stdio.h>
int main() {
void * fd = dlopen("libc.so.6", RTLD_LAZY);
void * real_sym = dlsym(fd, "accept");
void * curr_sym = dlsym(RTLD_NEXT, "accept");
printf("Real: %p Current: %p\n", real_sym, curr_sym);
return 0;
}
test.go:
// go build test.go
// Output: Real: 0x7f264583b7d0 Current: 0x7f2645b1b690
package main
// #cgo CFLAGS: -D_GNU_SOURCE
// #cgo LDFLAGS: -ldl
// #include <dlfcn.h>
import "C"
import "fmt"
func main() {
fp := C.dlopen(C.CString("libc.so.6"), C.RTLD_LAZY)
real_sym := C.dlsym(fp, C.CString("accept"))
curr_sym := C.dlsym(C.RTLD_NEXT, C.CString("accept"))
fmt.Printf("Real: %p Current: %p\n", real_sym, curr_sym)
}
Я получаю вывод Real: 0x7fd05559d7d0 Current: 0x7fd05559d7d0
при компиляции test.c
(gcc test.c -D_GNU_SOURCE -ldl
).Однако когда я строю test.go
, я вижу Real: 0x7f264583b7d0 Current: 0x7f2645b1b690
.
Я предполагаю, что go - это самообертывание некоторых символов, но я бы хотел точно знать, что происходит.Спасибо!
Пара дополнительных фрагментов после просмотра некоторых начальных комментариев.Я изменил test.c
, как показано ниже, а затем запустил цикл (while [ 1 ]; do ./a.out; done
).Он последовательно получает одинаковые адреса для меня (каждый раз по-разному).
// gcc test.c -D_GNU_SOURCE -ldl
// Output: Real: 0x7fd05559d7d0 Current: 0x7fd05559d7d0
#include <dlfcn.h>
#include <stdio.h>
int main() {
void * fd = dlopen("libc.so.6", RTLD_LAZY);
void * real_sym = dlsym(fd, "accept");
void * curr_sym = dlsym(RTLD_NEXT, "accept");
if(real_sym != curr_sym) {
printf("Real: %p Current: %p\n", real_sym, curr_sym);
}
return 0;
}
Я также попытался изменить код Go, чтобы проверить, связано ли это с тем, как Go вызывал C, но этовсе еще не было совпадения адресов:
// go build dos.go
// Output: Real: 0x7f264583b7d0 Current: 0x7f2645b1b690
package main
// #cgo CFLAGS: -D_GNU_SOURCE
// #cgo LDFLAGS: -ldl
// #include <dlfcn.h>
// #include <stdio.h>
// int doit() {
// void * fd = dlopen("libc.so.6", RTLD_LAZY);
// void * real_sym = dlsym(fd, "accept");
// void * curr_sym = dlsym(RTLD_NEXT, "accept");
// printf("Real: %p Current: %p\n", real_sym, curr_sym);
// return 0;
// }
import "C"
func main() {
C.doit()
}
Другой момент заключается в том, что я получаю совпадение двух адресов в коде C и Go, если я ищу символ malloc
вместо accept
.