关于exit()和对象析构

kiffa 2008-12-17 10:02:45
下面的代码会输出什么,为什么:

class A{
public:
~A(){ cout << "I die" << endl; }
};

A a;
void f(A a){ exit(0); };
void g(A a){ f(a); };

int main()
{
A a;
g(a);
}
...全文
367 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
黑夜愁客 2008-12-26
  • 打赏
  • 举报
回复
这些牛人,我好好学习
xiaoyisnail 2008-12-26
  • 打赏
  • 举报
回复
mark
haykey 2008-12-26
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 chenxiaohong3905 的回复:]
exit(0);是指退出main主函数,而其不会释放所有的资源(在mian函数分配的资源)
而第一个A对象实在mian函数之前分配的,由C++的运行库负责创建A对象,必然也是C++运行库复制释放全局的a对象。
main中的a对象是在main函数分配的,应该是main函数负责释放的,由于在main函数强制调用了exit函数,直接退出而导致main中的a不会析构。
[/Quote]
正解!《inside C++ object》又名<深度探索C++对象模型>这本书会告诉你很多的
kiffa 2008-12-25
  • 打赏
  • 举报
回复
感谢各位,尤其阿荣和陶大妈,看到标准这么一句话:“the program has undefined behavior.”,我就释然了。
陶大妈放心,我不会过分拘泥于细节,我只是好奇心比较重而已。。。

另17楼提出的cout问题,我倒还真没考虑过,也谢了。

再15楼大鹏说的TC++PL,我正是看到这一章才产生了这个疑问,才发帖来求教的。

wangkeyunanjing 2008-12-25
  • 打赏
  • 举报
回复
不是说exit不会去调用A的析构嘛。
arong1234 2008-12-25
  • 打赏
  • 举报
回复
所以说不好的设计总引起疑虑,不要在析购函数里做这种事情么:)你的程序需要最小化不清晰的东西,而不是增加. exit也应该在C++中尽量少使用

至于为什么不会循环递归,其首要条件是在析购中调用exit不应该在进入这个对象的析购,如果你写程序,你会怎么做到这一点(这个如果你学会首先问自己,设计技术就会提高很快)

我没研究过,但是我感觉CRT在delete一个全局变量前会把这个变量从自己维护的全局表中首先删除,因此如果这个全局变量触发另外一次exit,它自己已经不在那个表中

另外一种可能是exit自己设置一个全局标志,当自己被重入时,直接退出

如:
int exit(int code)
{
static int bCalled =0;
bCalled ++;
if(bCalled > 1) return code;
........
}


[Quote=引用 9 楼 kiffa 的回复:]
既然exit()会调用 A 的析构函数,那么如果 A 的析构函数里反过来调用exit(),像下面这样,会造成无穷递归吗?如果不会无穷递归,又是为什么?


C/C++ codeclass A
{
public:
~A(){exit(0);}
};

A a;
int main(){ exit(0); };
[/Quote]
speeder53 2008-12-25
  • 打赏
  • 举报
回复
mk
SearchLife 2008-12-25
  • 打赏
  • 举报
回复

cout是一个全局变量.所以在程序中使用的是printf函数,而且C++标准没有规定全局变量的析够顺序,以免产生一些问题。
SearchLife 2008-12-25
  • 打赏
  • 举报
回复

#include <iostream>
using namespace std;
class A
{
public:
A()
{
printf("%s\n","I");
}
A(const A&)
{
printf("%s\n","copy");
}
~A()
{
printf("%s\n","I die");
}
};

A a;
void f(A a)
{
exit(0);
// printf("%s\n","f()");
};
void g(A a)
{
f(a);
};
void fun(){ printf("%s\n","end here");} //增加个函数

int main()
{
printf("%s\n","start here");
atexit(fun); //exit时会调用

A a;
g(a);
}


全局对象是在进入main之前进行构造。
如果以return 退出 则局部的对象析构会调用。
它的过程是这样的:
1、先析构局部对象
2、将返回值返回给调用main的函数
3、调用exit函数,exit调用doexit,在doexit里有进行全局对象的析构,并且包含重复调用的限制。
4、在doexit的最后调用exitprocess.

所以,exit只负责析构全局对象,return 0可以析构局部对象并调用exit进行全局对象的析构
kiffa 2008-12-25
  • 打赏
  • 举报
回复
既然exit()会调用 A 的析构函数,那么如果 A 的析构函数里反过来调用exit(),像下面这样,会造成无穷递归吗?如果不会无穷递归,又是为什么?

class A
{
public:
~A(){exit(0);}
};

A a;
int main(){ exit(0); };
lann64 2008-12-25
  • 打赏
  • 举报
回复
TC++PL 9.4.1.1程序终止部分讲过。
如果一个程序利用标准库函数exit()终止,所有已经构造起来的静态对象的析构函数都将被调用。(静态、全局)......请注意,这意味着exit()并不立即终止程序。在析构函数里调用exit()有可能导致无穷递归。

另外,如果关注程序终止前所做的工作,还可以看看抛出异常和atexit()函数。
jackzhhuang 2008-12-25
  • 打赏
  • 举报
回复
一般只有汇编级才用exit退出进程
taodm 2008-12-25
  • 打赏
  • 举报
回复
摘自C++标准2003.
Calling the function
void exit(int);
declared in <cstdlib> (18.3) terminates the program without leaving the current block and hence without
destroying any objects with automatic storage duration (12.4). If exit is called to end a program during
the destruction of an object with static storage duration, the program has undefined behavior.
不要做语言律师!
踏岸寻柳 2008-12-25
  • 打赏
  • 举报
回复

#include <stdio.h>
#include <stdlib.h>

#include <iostream>

using namespace std;

class A
{
public:
A(int i)
: i(i)
{
cout << i << " : I born" << endl;
}
~A()
{
cout << i << " : I die" << endl;
}
private:
int i;
};

A a(1);

void f(A a)
{
exit(0);
};

void g(A a)
{
f(a);
};

int main()
{
A a(2);
g(a);
}
bfhtian 2008-12-18
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 chenxiaohong3905 的回复:]
exit(0);是指退出main主函数,而其不会释放所有的资源(在mian函数分配的资源)
而第一个A对象实在mian函数之前分配的,由C++的运行库负责创建A对象,必然也是C++运行库复制释放全局的a对象。
main中的a对象是在main函数分配的,应该是main函数负责释放的,由于在main函数强制调用了exit函数,直接退出而导致main中的a不会析构。
[/Quote]
调试下,应该是这样的
  • 打赏
  • 举报
回复
exit(0)是结束当前进程。。
M0605050215 2008-12-17
  • 打赏
  • 举报
回复
学习了
lann64 2008-12-17
  • 打赏
  • 举报
回复
给程序增加一点东西就看清楚一些了。
#include <iostream>
using namespace std;
class A
{
public:
~A()
{
cout << "I die" << endl;
}
};

A a;
void f(A a)
{
exit(0);
};
void g(A a)
{
f(a);
};
void fun(){ cout<<"End here!"<<endl;} //增加个函数
int main()
{
atexit(fun); //exit时会调用
A a;
g(a);
}
lann64 2008-12-17
  • 打赏
  • 举报
回复
exit调用的终止处理程序里析构了全局的A a。
newzai 2008-12-17
  • 打赏
  • 举报
回复
exit(0);是指退出main主函数,而其不会释放所有的资源(在mian函数分配的资源)
而第一个A对象实在mian函数之前分配的,由C++的运行库负责创建A对象,必然也是C++运行库复制释放全局的a对象。
main中的a对象是在main函数分配的,应该是main函数负责释放的,由于在main函数强制调用了exit函数,直接退出而导致main中的a不会析构。
加载更多回复(2)

64,647

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧