免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2512 | 回复: 0
打印 上一主题 下一主题

[C++] 搞不定:GCC编译 动态库 例外捕获 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-05-06 16:48 |只看该作者 |倒序浏览
最近遇到一个棘手的环境移植问题,原来的程序在AIX下运行没问题,但移植到LINUX(redhat)就有事,究其原因是如下两个要求无法同时达到:
  1)动态库与主程序同名全局变量拥有独立的地址(即指向不同的内存)
  2)在动态库或主程序中能捕获对方抛出的例外
不知道用什么样的GCC选项能做到!?

以下是我的测试程序:

---- exception.h ----
  1. class CError
  2. {
  3. };
复制代码
---- libf1.cpp ----
  1. #include "exception.h"
  2. #include <stdio.h>

  3. struct XMe {
  4.   void (* ff)(void);
  5. };
  6. char * ppp = NULL; // 全局变量,由主程序赋值
  7. XMe * pMe = NULL;

  8. extern "C" void f1() {
  9.     printf("libf1: %X, %s\n", &ppp, ppp); // 打印下自己的地址和值
  10.     try {
  11.        pMe->ff();
  12.     } catch (CError & e) {
  13.        printf("f1: catch CError from main.\n"); // 接获主程序的例外
  14.     } catch (...) {
  15.        printf("f1: catch unknown exception from main.\n"); // 无法探查出主程序是何例外
  16.     }
  17.     printf("f1: throw CError ... \n");
  18.     throw CError(); // 抛出例外
  19. }
复制代码
---- main.cpp ----
  1. #include <iostream>
  2. #include <dlfcn.h>
  3. #include "exception.h"
  4. using namespace std;

  5. char * ppp = "I am main"; // 全局变量,同名的

  6. static char * libf1 = "YOU!!!";

  7. void f0 () {
  8.    throw CError();
  9. }

  10. struct XMe {
  11.    void (* ff)(void);
  12. };
  13. XMe me = {f0};

  14. main() {

  15.     // 这一段是证明在本模块内,例外抛出和接获都正常
  16.     try {
  17.             f0();
  18.     } catch (CError& e) {
  19.             cout << "f0: CError. " << endl;
  20.     } catch (...) {
  21.             cout << "f0: unknown exception - expected: CError. " << endl;
  22.     }
  23.     // 以下开始测试主程序与动态库之间的交互
  24.     void *lib_f1;
  25.     void (*f1_call)();
  26.     char ** p4libf1 = NULL;
  27.     XMe ** p4libf1me = NULL;

  28.     if (!(lib_f1=dlopen("./libf1.so",RTLD_LAZY))) { // 打开动态库
  29.             cout << "Can't open ./libf1.so." << endl;
  30.             exit(1);
  31.     }
  32.     if (!(f1_call=(void (*)())dlsym(lib_f1,"f1"))) { // 定位到函数f1
  33.             cout << "Can't bind f1." << endl;
  34.             exit(2);
  35.     }
  36.     if ((p4libf1me=(XMe **)dlsym(lib_f1,"pMe"))) { // 定位到全局变量pMe
  37.            *p4libf1me = &me; // 把主程序的函数赋予他
  38.     }
  39.     if ((p4libf1=(char **)dlsym(lib_f1,"ppp"))) { // 定位到全局变量ppp
  40.            *p4libf1 = libf1; // 把主程序的某个不同于自己的ppp的地址赋予他
  41.     }
  42.     printf("main0: %X, %s\n", &ppp, ppp); // 打印自己
  43.     try {
  44.             (*f1_call)(); // 调用动态库的函数
  45.     } catch (CError& e) {
  46.             cout << "f1: CError." << endl;
  47.     } catch (...) {
  48.             cout << "f1: unknown exception - expected: CError. " << endl;
  49.     }
  50.     dlclose(lib_f1);
  51. }
复制代码
---- makefile ----
  1. CC = g++

  2. all: main libf1.so

  3. main: main.cpp exception.h
  4. # 这样例外才能正确接获(so和main之间)
  5.         $(CC) -Wl,-E -g -ldl -o test_exception test_exception.cpp
  6. # 这样才能让同名全局变量指向不同地址(so和main之间)
  7. #        $(CC) -g -ldl -o test_exception test_exception.cpp
  8. # 然而,鱼和熊掌不可兼得,咋办?
  9. libf1.so: libf1.cpp exception.h
  10.         $(CC) -g -shared -o libf1.so libf1.cpp

  11. clean:
  12.         rm -f *.o libf?.so core* a.out main
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP