이전 포스트와 관련해서
다시 linux man page를 찾아보니 dlerror() 예제에서
dlerror() 를 호출하여 error message를 clear 시키고 있었음.
Load the math library, and print the cosine of 2.0:
#include <stdio.h> #include <stdlib.h> #include <dlfcn.h> int main(int argc, char **argv) { void *handle; double (*cosine)(double); char *error; handle = dlopen("libm.so", RTLD_LAZY); if (!handle) { fprintf(stderr, "%s\n", dlerror()); exit(EXIT_FAILURE); } dlerror(); /* Clear any existing error */ /* Writing: cosine = (double (*)(double)) dlsym(handle, "cos"); would seem more natural, but the C99 standard leaves casting from "void *" to a function pointer undefined. The assignment used below is the POSIX.1-2003 (Technical Corrigendum 1) workaround; see the Rationale for the POSIX specification of dlsym(). */ *(void **) (&cosine) = dlsym(handle, "cos"); if ((error = dlerror()) != NULL) { fprintf(stderr, "%s\n", error); exit(EXIT_FAILURE); } printf("%f\n", (*cosine)(2.0)); dlclose(handle); exit(EXIT_SUCCESS); } |
-----------------------------------------------------------------------------------------
이전 포스트 내용
-----------------------------------------------------------------------------------------
오늘 dlsym 관련 황당한 일이 있어 이를 글로 남김
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char **argv) {
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen ("/lib/libm.so.6", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
cosine = dlsym(handle, "cos");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
printf ("%f\n", (*cosine)(2.0));
dlclose(handle);
}
|
하지만 위의 예제를 가지고 Android NDK로 빌드하여 Android 상에서 실행하였지만
"Symbol not found: " 라는 메세지와 함께 종종 dlsym이 실패하는 경우를 확인할 수 있었다.
(Android NDK r8d, Android target의 version은 JBP)
생성된 shared library의 symbol을 확인하였을때는
해당 함수는 naming mangling(http://en.wikipedia.org/wiki/Name_mangling) 문제 없이 export 되어 있어서 library의 open에 성공하여 symbol 찾는데는 문제가 없어 보였다.
이래 저래 검색하다 아래와 같은 Android bug report를 검색하게 되었다. dlsym에서 symbol을 못찾는 문제와 조금 다른 bug report지만 dlerror() 메세지 처리에서 있어 GetLastError()와 같은 thread unsafe 한 상황이 발생할 수 있음을 알 수 있다.
아래의 답변이 가장 정리가 잘된듯 하다.
Some important rules:
That's all :)
|
(http://stackoverflow.com/questions/10785740/dynamic-c-c-lib-for-android-2-2-error-symbol-not-found)
위에서 답변과 같이 아래와 같이 dlsym의 error check 부분을 수정하여 정상 동작 함을 확인.
if ((error = dlerror()) != NULL) && (cosine == NULL)) {
|
하지만 Linux man page를 확인하니 다음의 메세지가 있었음.
dlsym()
|
그래서 아래 처럼 수정하는게 맞을 것 같다...
dlerror(); // to clear dlerror message
cosine = dlsym(handle, "cos");
if ((error = dlerror()) != NULL) && (cosine == NULL)) {
|
[참고] nm, readelf를 사용하여 shared library의 symbol확인
The standard tool for listing symbols is
nm , you can use it simply like this:
If you want to see symbols of a C++ library, add the "-C" option which demangle the symbols (it's far more readable demangled).
If your .so file is in elf format, you will have to use
readelf program to extract symbol information from the binary.
You only should extract those that are defined in this .so file, not in the libraries referenced by it. Seventh column should contain a number in this case. You can extract the corresponding lines with
awk :인인
Update: Thanks to Pavel Shved and Gaspin, I've updated the answer
|
GetLastError()는 thread safety한 함수입니다. last error는 tls에 저장되고 있습니다.
답글삭제감사합니다.
답글삭제