搞不定:GCC编译 动态库 例外捕获
最近遇到一个棘手的环境移植问题,原来的程序在AIX下运行没问题,但移植到LINUX(redhat)就有事,究其原因是如下两个要求无法同时达到:
1)动态库与主程序同名全局变量拥有独立的地址(即指向不同的内存)
2)在动态库或主程序中能捕获对方抛出的例外
不知道用什么样的GCC选项能做到!?
以下是我的测试程序:
---- exception.h ----
- class CError
- {
- };
复制代码---- libf1.cpp ----
- #include "exception.h"
- #include <stdio.h>
- struct XMe {
- void (* ff)(void);
- };
- char * ppp = NULL; // 全局变量,由主程序赋值
- XMe * pMe = NULL;
- extern "C" void f1() {
- printf("libf1: %X, %s\n", &ppp, ppp); // 打印下自己的地址和值
- try {
- pMe->ff();
- } catch (CError & e) {
- printf("f1: catch CError from main.\n"); // 接获主程序的例外
- } catch (...) {
- printf("f1: catch unknown exception from main.\n"); // 无法探查出主程序是何例外
- }
- printf("f1: throw CError ... \n");
- throw CError(); // 抛出例外
- }
复制代码---- main.cpp ----
- #include <iostream>
- #include <dlfcn.h>
- #include "exception.h"
- using namespace std;
- char * ppp = "I am main"; // 全局变量,同名的
- static char * libf1 = "YOU!!!";
- void f0 () {
- throw CError();
- }
- struct XMe {
- void (* ff)(void);
- };
- XMe me = {f0};
- main() {
- // 这一段是证明在本模块内,例外抛出和接获都正常
- try {
- f0();
- } catch (CError& e) {
- cout << "f0: CError. " << endl;
- } catch (...) {
- cout << "f0: unknown exception - expected: CError. " << endl;
- }
- // 以下开始测试主程序与动态库之间的交互
- void *lib_f1;
- void (*f1_call)();
- char ** p4libf1 = NULL;
- XMe ** p4libf1me = NULL;
- if (!(lib_f1=dlopen("./libf1.so",RTLD_LAZY))) { // 打开动态库
- cout << "Can't open ./libf1.so." << endl;
- exit(1);
- }
- if (!(f1_call=(void (*)())dlsym(lib_f1,"f1"))) { // 定位到函数f1
- cout << "Can't bind f1." << endl;
- exit(2);
- }
- if ((p4libf1me=(XMe **)dlsym(lib_f1,"pMe"))) { // 定位到全局变量pMe
- *p4libf1me = &me; // 把主程序的函数赋予他
- }
- if ((p4libf1=(char **)dlsym(lib_f1,"ppp"))) { // 定位到全局变量ppp
- *p4libf1 = libf1; // 把主程序的某个不同于自己的ppp的地址赋予他
- }
- printf("main0: %X, %s\n", &ppp, ppp); // 打印自己
- try {
- (*f1_call)(); // 调用动态库的函数
- } catch (CError& e) {
- cout << "f1: CError." << endl;
- } catch (...) {
- cout << "f1: unknown exception - expected: CError. " << endl;
- }
- dlclose(lib_f1);
- }
复制代码---- makefile ----
- CC = g++
- all: main libf1.so
- main: main.cpp exception.h
- # 这样例外才能正确接获(so和main之间)
- $(CC) -Wl,-E -g -ldl -o test_exception test_exception.cpp
- # 这样才能让同名全局变量指向不同地址(so和main之间)
- # $(CC) -g -ldl -o test_exception test_exception.cpp
- # 然而,鱼和熊掌不可兼得,咋办?
- libf1.so: libf1.cpp exception.h
- $(CC) -g -shared -o libf1.so libf1.cpp
- clean:
- rm -f *.o libf?.so core* a.out main
复制代码
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论