退出和返回有什么区别? [英] What is the difference between exit and return?

查看:19
本文介绍了退出和返回有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从 C 程序中的任何位置调用时,C 编程中的 return 和 exit 语句有什么区别?

解决方案

  • return 从当前函数返回;它是一个语言关键字,例如 forbreak.
  • exit() 终止整个程序,无论您从哪里调用它.(在刷新 stdio 缓冲区等之后).

两者做(几乎)相同的事情的唯一情况是在 main() 函数中,因为从 main 的返回执行 exit().p>

在大多数 C 实现中,main 是一个真正的函数,由一些启动代码调用,执行类似于 int ret = main(argc, argv); 的操作.退出(ret);.C 标准保证在 main 返回时会发生等价的事情,但是实现会处理它.

return 示例:

#include <stdio.h>无效 f(){printf("正在执行 f
");返回;}诠释主要(){F();printf("从 f
 返回");}

如果你执行这个程序,它会打印:

<块引用>

执行 f从 f 回来

exit()的另一个例子:

#include <stdio.h>#include <stdlib.h>无效 f(){printf("正在执行 f
");退出(0);}诠释主要(){F();printf("从 f
 返回");}

如果你执行这个程序,它会打印:

<块引用>

执行 f

你永远不会得到从 f 回来".还要注意调用库函数 exit() 所必需的 #include <stdlib.h>.

还要注意exit()的参数是一个整数(它是launcher进程可以得到的进程的返回状态;常规用法是0表示成功,其他任何值表示错误).

return 语句的参数是函数的返回类型.如果函数返回void,可以省略函数末尾的return.

最后一点,exit() 有两种风格:_exit()exit().表单之间的区别在于 exit() (并从 main 返回)在真正之前调用使用 atexit()on_exit() 注册的函数在 _exit()(来自 #include <unistd.h> 或其同义词 _Exit from #include <stdlib.h> 时终止进程code>) 立即终止进程.

现在还有一些 C++ 特有的问题.

C++ 在退出函数(return-ing)时比 C 执行更多的工作.具体来说,它调用超出范围的本地对象的析构函数.在大多数情况下,程序员不会在乎进程停止后程序的状态,因此不会有太大的不同:分配的内存将被释放,文件资源关闭等等.但是你的析构函数是否执行 IO 可能很重要.例如,本地创建的自动 C++ OStream 不会在调用 exit 时被刷新,并且您可能会丢失一些未刷新的数据(另一方面,静态 OStream 将被刷新).

如果您使用良好的旧 C FILE* 流,则不会发生这种情况.这些将在 exit() 上刷新.实际上,规则与注册退出函数的规则相同,FILE* 将在所有正常终止时刷新,包括 exit(),但不调用 _exit() 或 abort().

您还应该记住,C++ 提供了第三种退出函数的方法:抛出异常.这种退出函数的方式调用析构函数.如果在调用者链中的任何地方都没有捕获到它,则异常可以向上传递到 main() 函数并终止进程.

如果您从 main()exit() 中的任何位置调用 return,则将调用静态 C++ 对象(全局)的析构函数你的程序.如果程序使用 _exit()abort() 终止,则不会调用它们.abort() 在调试模式下最有用,目的是立即停止程序并获取堆栈跟踪(用于事后分析).它通常隐藏在 assert() 宏后面,仅在调试模式下有效.

exit() 什么时候有用?

exit() 表示你想立即停止当前进程.当我们遇到某种无法恢复的问题时,它可能对错误管理有一些用处,这些问题不允许您的代码再做任何有用的事情.当控制流很复杂并且错误代码必须一直向上传播时,它通常很方便.但请注意,这是不好的编码习惯.在大多数情况下,静默结束进程是更糟糕的行为,应该首选实际的错误管理(或者在 C++ 中使用异常).

如果在库中直接调用 exit() 尤其糟糕,因为它会使库用户陷入困境,并且应该由库用户选择是否实施某种错误恢复.如果您想举例说明为什么从库中调用 exit() 不好,例如,人们会问 这个问题.

在支持它的操作系统上,exit() 作为结束由 fork() 启动的子进程的方式是无可争议的合法使用.回到 fork() 之前的代码通常是个坏主意.这就是解释为什么 exec() 系列的函数永远不会返回给调用者的理由.

What is difference between return and exit statement in C programming when called from anywhere in a C program?

解决方案

  • return returns from the current function; it's a language keyword like for or break.
  • exit() terminates the whole program, wherever you call it from. (After flushing stdio buffers and so on).

The only case when both do (nearly) the same thing is in the main() function, as a return from main performs an exit().

In most C implementations, main is a real function called by some startup code that does something like int ret = main(argc, argv); exit(ret);. The C standard guarantees that something equivalent to this happens if main returns, however the implementation handles it.

Example with return:

#include <stdio.h>

void f(){
    printf("Executing f
");
    return;
}

int main(){
    f();
    printf("Back from f
");
}

If you execute this program it prints:

Executing f
Back from f

Another example for exit():

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

void f(){
    printf("Executing f
");
    exit(0);
}

int main(){
    f();
    printf("Back from f
");
}

If you execute this program it prints:

Executing f

You never get "Back from f". Also notice the #include <stdlib.h> necessary to call the library function exit().

Also notice that the parameter of exit() is an integer (it's the return status of the process that the launcher process can get; the conventional usage is 0 for success or any other value for an error).

The parameter of the return statement is whatever the return type of the function is. If the function returns void, you can omit the return at the end of the function.

Last point, exit() come in two flavors _exit() and exit(). The difference between the forms is that exit() (and return from main) calls functions registered using atexit() or on_exit() before really terminating the process while _exit() (from #include <unistd.h>, or its synonymous _Exit from #include <stdlib.h>) terminates the process immediately.

Now there are also issues that are specific to C++.

C++ performs much more work than C when it is exiting from functions (return-ing). Specifically it calls destructors of local objects going out of scope. In most cases programmers won't care much of the state of a program after the processus stopped, hence it wouldn't make much difference: allocated memory will be freed, file ressource closed and so on. But it may matter if your destructor performs IOs. For instance automatic C++ OStream locally created won't be flushed on a call to exit and you may lose some unflushed data (on the other hand static OStream will be flushed).

This won't happen if you are using the good old C FILE* streams. These will be flushed on exit(). Actually, the rule is the same that for registered exit functions, FILE* will be flushed on all normal terminations, which includes exit(), but not calls to _exit() or abort().

You should also keep in mind that C++ provide a third way to get out of a function: throwing an exception. This way of going out of a function will call destructor. If it is not catched anywhere in the chain of callers, the exception can go up to the main() function and terminate the process.

Destructors of static C++ objects (globals) will be called if you call either return from main() or exit() anywhere in your program. They wont be called if the program is terminated using _exit() or abort(). abort() is mostly useful in debug mode with the purpose to immediately stop the program and get a stack trace (for post mortem analysis). It is usually hidden behind the assert() macro only active in debug mode.

When is exit() useful ?

exit() means you want to immediately stops the current process. It can be of some use for error management when we encounter some kind of irrecoverable issue that won't allow for your code to do anything useful anymore. It is often handy when the control flow is complicated and error codes has to be propagated all way up. But be aware that this is bad coding practice. Silently ending the process is in most case the worse behavior and actual error management should be preferred (or in C++ using exceptions).

Direct calls to exit() are especially bad if done in libraries as it will doom the library user and it should be a library user's choice to implement some kind of error recovery or not. If you want an example of why calling exit() from a library is bad, it leads for instance people to ask this question.

There is an undisputed legitimate use of exit() as the way to end a child process started by fork() on Operating Systems supporting it. Going back to the code before fork() is usually a bad idea. This is the rationale explaining why functions of the exec() family will never return to the caller.

这篇关于退出和返回有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆