免费注册 查看新帖 |

Chinaunix

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

[函数] 关于子进程中的析构函数使用的问题。 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-08-16 11:28 |只看该作者 |倒序浏览
今天在调试程序的时候,想看一下析构函数的调用情况。发现在kill -USR2 PID,杀掉程序后,整个程序调用了2次析构函数。于是写了一个类似结构代码如下:


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <signal.h>
  6. #include <sys/time.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <pthread.h>

  10. class CTestClassA
  11. {
  12. public:
  13.         CTestClassA()
  14.         {
  15.                 printf(" this[%X] CTestClassA::CTestClassA()\n",this);
  16.         }
  17.         ~CTestClassA()
  18.         {
  19.                 printf(" this[%X] d[%X] CTestClassA::~CTestClassA()\n",this,&this->d);
  20.         }
  21. public:
  22.          int d;
  23. };

  24. CTestClassA             cTestClassA;
  25. CTestClassA             cTestClassB;
  26. char                         cShutdownFlag = 0;

  27. void sSleep(int iTime);
  28. void onUSR2(int iSignal);
  29. int  DaemonInit();

  30. int main()
  31. {
  32.         cTestClassA.d = 1;
  33.         cTestClassB.d = 2;
  34.         DaemonInit();
  35.                 signal(SIGUSR2, onUSR2);

  36.                 while(!cShutdownFlag)
  37.                {
  38.                        printf(" main is running ...\n");
  39.                        sSleep(1);
  40.                }

  41.                return 0;
  42. }

  43. void sSleep(int iTime)
  44. {
  45.         timeval sTime;
  46.         sTime.tv_sec    = iTime;
  47.         sTime.tv_usec   = 0;
  48.         select(0,NULL,NULL,NULL,&sTime);
  49. }

  50. void onUSR2(int iSignal)
  51. {
  52.         cShutdownFlag = 1;
  53.         sSleep(2);
  54.         exit(0);
  55. }

  56. int  DaemonInit()
  57. {
  58.     pid_t pid;

  59.     pid = fork();
  60.     if( pid < 0 )
  61.         return -1;
  62.     if( 0 == pid )
  63.     {
  64.         if( setsid() < 0 )
  65.                return -2;
  66.         umask(0);
  67.     }
  68.     else
  69.     {
  70.         exit(0);
  71.     }

  72.     signal(SIGHUP,SIG_IGN);
  73.     return 0;
  74. }
复制代码


在程序运行后,用kill -USR2 PID 命令将函数杀死。调试时输出的日志信息如下:
bash-2.03$ ./q2
this[28528] CTestClassA::CTestClassA()
this[2852C] CTestClassA::CTestClassA()
main is running ...
this[2852C] d[2852C] CTestClassA::~CTestClassA()
this[28528] d[28528] CTestClassA::~CTestClassA()
bash-2.03$  main is running ...
main is running ...
this[2852C] d[2852C] CTestClassA::~CTestClassA()
this[28528] d[28528] CTestClassA::~CTestClassA()
bash-2.03$

我现在不理解的地方如下:
1.为什么会调用2次析构函数?
  我想这个是和fork()函数有关系的。这个我可以理解。
2.为什么2次调用析构函数的地址是一样的?
  调用fork()函数后,子进程会拷贝父进程的全部变量。但是为什么他们的内存地址还是一样的呢?不理解。请大家帮忙解惑。
调试环境Solaris 8.0,gcc version 2.95.3。

论坛徽章:
0
2 [报告]
发表于 2006-08-16 13:20 |只看该作者
题都城南庄 -崔护
去年今日此门中,人面桃花相映红。
人面不知何处去,桃花依旧笑春风。

顶起来先~~~~~~~~

论坛徽章:
0
3 [报告]
发表于 2006-08-16 13:31 |只看该作者
你的问题
1. 因为FORK
2. 也是因为FORK。地址一样的但是在不同的地址空间

论坛徽章:
0
4 [报告]
发表于 2006-08-16 13:38 |只看该作者
yes, fork()!

论坛徽章:
0
5 [报告]
发表于 2006-08-16 13:41 |只看该作者
fork的原来是什么意思(字的来历)我不知道。

论坛徽章:
0
6 [报告]
发表于 2006-08-16 13:41 |只看该作者
fork的原来是什么意思(字的来历)我不知道。

论坛徽章:
0
7 [报告]
发表于 2006-08-16 13:43 |只看该作者
fork调用后,地址空间复制.

由于在fork前,只在父进程中,创建了CTestClassAD的两个实例cTestClassA,cTestClassB,会调用构造函数两次,执行到fork返回后,父子进程中各有cTestClassA, cTestClassB,然后父进程退出,调用两次析构函数.

子进程收到SIGUSR2退出,全局实例销毁,又调用两次析构函数.

你把cTestClassA,cTestClassB定义为局部变量在测试一下结果,看一下子进程有没有输出.

论坛徽章:
0
8 [报告]
发表于 2006-08-16 15:46 |只看该作者
原帖由 思一克 于 2006-8-16 13:31 发表
你的问题
1. 因为FORK
2. 也是因为FORK。地址一样的但是在不同的地址空间


能不能再解释一下 第二个,还是有些不清楚。

我把测试代码修改了一下,把onUSR2()函数中的 exit(0)函数取掉了。这样就保证从main函数中退出,也保证在main函数中局部变量也可以调用析构函数释放资源。


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <signal.h>
  6. #include <sys/time.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <pthread.h>

  10. class CTestClassA
  11. {
  12. public:
  13.         CTestClassA()
  14.         {
  15.                 printf(" this[%X] CTestClassA::CTestClassA()\n",this);
  16.         }
  17.         ~CTestClassA()
  18.         {
  19.                 printf(" this[%X] d[%X] CTestClassA::~CTestClassA()\n",this,&this->d);
  20.         }
  21. public:
  22.                 int d;
  23. };

  24. CTestClassA             cTestClassA;
  25. CTestClassA             cTestClassB;
  26. char                    cShutdownFlag = 0;

  27. void sSleep(int iTime);
  28. void onUSR2(int iSignal);
  29. int  DaemonInit();

  30. int main()
  31. {
  32.         CTestClassA  cTestClassC;
  33.         cTestClassA.d = 1;
  34.         cTestClassB.d = 2;
  35.         DaemonInit();
  36.         signal(SIGUSR2, onUSR2);

  37.         while(!cShutdownFlag)
  38.         {
  39.                 printf(" main is running ...\n");
  40.                 sSleep(1);
  41.         }

  42.         return 0;
  43. }

  44. void sSleep(int iTime)
  45. {
  46.         timeval sTime;
  47.     sTime.tv_sec    = iTime;
  48.     sTime.tv_usec   = 0;
  49.         select(0,NULL,NULL,NULL,&sTime);
  50. }

  51. void onUSR2(int iSignal)
  52. {
  53.         printf(" recv USR2 \n");
  54.         cShutdownFlag = 1;
  55.         sSleep(2);
  56.         return ;
  57. }

  58. int  DaemonInit()
  59. {
  60.     pid_t pid;

  61.     pid = fork();
  62.     if( pid < 0 )
  63.         return -1;

  64.     if( 0 == pid )
  65.     {
  66.         if( setsid() < 0 )
  67.                     return -2;
  68.         umask(0);
  69.     }
  70.    else
  71.     {
  72.         exit(0);
  73.     }

  74.         signal(SIGHUP,SIG_IGN);

  75.     return 0;
  76. }
复制代码

论坛徽章:
0
9 [报告]
发表于 2006-08-16 15:48 |只看该作者
日志信息:
this[285A8] CTestClassA::CTestClassA()
this[285AC] CTestClassA::CTestClassA()
this[FFBEF95C] CTestClassA::CTestClassA()
main is running ...
this[285AC] d[285AC] CTestClassA::~CTestClassA()
this[285A8] d[285A8] CTestClassA::~CTestClassA()
bash-2.03$  main is running ...
main is running ...
recv USR2
this[FFBEF95C] d[FFBEF95C] CTestClassA::~CTestClassA()
this[285AC] d[285AC] CTestClassA::~CTestClassA()
this[285A8] d[285A8] CTestClassA::~CTestClassA()

论坛徽章:
0
10 [报告]
发表于 2006-08-16 15:49 |只看该作者
两个不同地址空间的相同地址。

你一个程序FORK()8个,一个变量的8个地址多数情况都是一样的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP