aut*_*456 1 c error-handling shared-libraries segmentation-fault dlopen
有这个文件:
\n\n加一c
\n\nint op(int i){ return i+1; }\nRun Code Online (Sandbox Code Playgroud)\n\n主程序
\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <dlfcn.h>\n\nint main(int argc, char **argv){\n if (argc<3){\n printf("usage %s <library> <number>\\n",argv[0]);\n exit(1);\n }\n\n char *lname = argv[1];\n int num = atoi(argv[2]);\n void *handle = dlopen(lname, RTLD_LAZY);\n if(!handle)\n perror("dlopen");\n\n int (*opp)(int);\n opp=dlsym(handle, "op");\n if(!opp)\n perror("dlsym");\n\n printf("number before:%i\\nnumber after:%i\\n",num,opp(num)); \n dlclose(handle);\n}\nRun Code Online (Sandbox Code Playgroud)\n\n编译为:
\n\n$cc -fPIC -shared -o plusone.so -ldl plusone.c\n$cc -o main.exe -ldl -Wpedantic main.c\nwarning: ISO C forbids assignment between function pointer and \xe2\x80\x98void *\xe2\x80\x99 [-Wpedantic]\n$ls\nmain.c main.exe plusone.so main.exe\n$main.exe\nusage main.exe <library> <number>\n$main plusone.so 1\ndlopen: Success\ndlsym: Success\nSegmentation fault\nRun Code Online (Sandbox Code Playgroud)\n\n为什么会出现段错误?
\n\n从 bash 输出中可以看出, 和 都dlopen成功dlsym(但它们甚至不应该输出,否则这意味着条件为真,并且这些函数的返回值是 NULL? - 正如条件一样)。但即使返回的“成功” perror,我也无法重现段错误,因为不知道错误在哪里。
为什么会出现段错误?
很可能是因为opp等于尝试被调用的NULL时刻。opp(num)
您没有正确处理对dlopen()和 的调用的错误dlysym(),尽管代码测试了结果,但它没有对这两个函数的失败采取正确的操作。
这段代码
void *handle = dlopen(lname, RTLD_LAZY);
if(!handle)
perror("dlopen");
Run Code Online (Sandbox Code Playgroud)
dlopen()返回时正确分支NULL指示错误,但随后代码执行错误的操作。
dlopen()没有设置errno,因此使用perror()记录错误是没有意义的,因为perror()依赖于指示errno错误,而事实并非如此。所以在失败时dlopen()你会看到perror()打印
dlopen: Success
Run Code Online (Sandbox Code Playgroud)
这对被调用的事实具有误导性和收缩性perror(),实际上只有在dlopen()returned时才会发生NULL,表明失败。如果dlopen()成功,perror()则根本不会被调用,也不会打印任何内容。
调用 时也会出现同样的错误dlsym()。
dl*()要检索有关函数系列成员失败的错误信息,请使用dlerror().
有关如何正确且完整地实施错误处理的示例,请参见下文:
void *handle = dlopen(...);
if (!handle)
{
fprintf(stderr, "dlopen: %s\n", dlerror());
exit(EXIT_FAILURE); /* Or do what ever to avoid using the value of handle. */
}
#ifdef DEBUG
else
{
fputs("dlopen: Success\n", stderr);
}
#endif
Run Code Online (Sandbox Code Playgroud)
应采用相同的方法来处理 的结果dlsym()。
除此之外,与观察到的行为无关,代码dlclose()在使用有效的handle.