0

我正在考虑exit()仅出于教育目的实现我自己的功能。我知道如果操作系统允许您可以操作地址(例如操作系统不会让您操作地址 0,它会导致崩溃)。
所以我想为什么不发送0到那个地址return 0返回。

int main(){
// code...
return 0;
}

return 0操作系统返回“成功”,对吗?但它是哪个地址?我如何得到它?C 标准库中的实际 exit() 是否以这种方式实现?

4

8 回答 8

4

当你return 0,你不返回一个地址。您正在返回0。当进程返回值 0 时,它被认为是正常终止。您可以返回一个非零值(最多 255),调用进程可能会将其解释为消息。

让我们用一个示例命令来看看这个grep foobar fubarfoobar如果文件中有模式,它将返回 0(成功)fubarfoobar如果文件中没有,它将返回 1 fubar。当没有文件名为fubar. rturn 值可以在使该命令评估成功或失败原因的脚本中进行解释。

于 2013-08-06T17:44:17.240 回答
4

退出代码(最终)存储在进程控制块中,以便操作系统可以将结果值报告给其他进程。

http://www.cs.auckland.ac.nz/compsci340s2c/lectures/lecture06.pdf

但是,return声明并不是这样做的。您的运行时库实际上main或多或少地像普通函数一样调用,获取返回值(在 Intel 上,类型的返回值int将存储在EAX寄存器中),然后请求内核将其写入 TCB。 exit()还调用内核来写入 TCB 的这个成员。

于 2013-08-06T17:59:29.600 回答
2

return 0;inmainreturn任何地方一样工作;它返回到调用它的地方。当您启动一个程序时,系统不会启动它main,而是在某个执行大量初始化的启动地址启动它,然后是:

exit( main(/*...*/) );

换句话说,exit不模拟从main;的返回。从main电话中返回exit_exit然后在调用一些系统特定的函数告诉系统停止进程(在 Unix 下)之前, exit 会进行很多关闭操作。

你不能自己实现exit,因为你无法找到它需要的信息:需要调用atexit的注册函数列表,具有静态生命周期的对象的析构函数列表等。

于 2013-08-06T18:01:17.283 回答
2

我认为这里的主要混淆是认为这main是 C++ 程序中发生的第一件事和最后一件事。虽然它是您程序的 [1] 的第一部分,但应用程序中通常有一些代码用于设置一些东西、解析命令行参数、打开/初始化标准 I/O(cincout等)和其他类似的东西, 发生在 BEFOREmain被调用。并且main本质上只是另一个函数,由 C++ 运行时功能调用,它可以“在之前修复问题main”。

所以,当main返回时,它会回到调用它的代码,然后清理需要清理的东西(关闭标准 I/O 通道和许多其他类似的东西),然后通过调用一些 OS 函数来真正完成“终止此过程”。作为这个“终止这个进程”的一部分,功能是(在大多数操作系统中)向操作系统发出“成功或失败”信号的一种方式,以便监控应用程序的其他一些进程可以确定“是否一切正常”。这就是最终0(或者1如果你使用return 1;in main)结束的地方。

[1] 如果有带有构造函数的静态对象是用户代码的一部分,那么这些将在main[或至少在main属于用户应用程序的任何代码]中的任何代码执行之前执行。

于 2013-08-06T19:13:31.790 回答
1

你的困惑是因为不明白做什么return。以这个函数为例:

int add(int x, int y)
{
   return (x + y);
}

上述函数中的 return 和函数末尾的 return 语句main完全相同,从语言的角度来看,它们的含义相同。其含义是向调用者返回一个整数。调用者从这个值中得到什么完全是另一回事,这取决于调用者调用所述函数的意图。假设我可以调用add(7, 9);增加两个 GPA 成绩,而另一个程序员可能会调用它来查找几个银行账户中所有资金的总和。

Nowmain被视为一个特殊函数,因为它是操作系统,或者更具体地说是它的加载器,调用成为您的程序的第一个函数。程序完成后,任何main返回都可能意味着基于操作系统语义的任何内容。该值与任何内存地址无关。

旁白:根据标准,在 C++(和 C99 以上)中,return 0;可以省略该语句以表示程序成功终止。

于 2013-08-06T18:00:41.823 回答
0

当你有 afunction时,它就有一个类型。它可以是int,void或其他。如果函数不是 void,那么它必须返回一个值。在我们的例子中,它的值return通常是一个代码。约定是,如果为 0,则没有错误,而其他值是错误代码。mainintreturn

于 2013-08-06T18:11:52.410 回答
0

如果您的 C++ abi 库实现了__cxa_atexit您可以使用的符号atexit

AFAIK 语言并没有真正提供其他安全的方法来执行程序停止执行时用户定义的操作。

于 2013-08-06T18:09:53.887 回答
0

如果我的理解是正确的,将会有一个 SIGCHLD 信号将在退出时发送到包含返回值的主外壳......这应该在 PCB 被内核破坏时发生......

但是,如果您想在退出代码时连接某些功能,您可以根据 POSIX 实现在 atexit() 处注册一个处理程序。

我不认为您可以修改返回值在用户级别的传播方式,因为程序的控制权在另一个进程(您无权访问)中到达 PC。

于 2013-08-06T18:06:50.163 回答