显然,这是一种很好的做法。那不用说了。我每次都会在示例代码中看到它(例如socket()
、fork()
或malloc()
,仅举几例)。我知道这样做,我只是不明白为什么这样做。他们是否容易经常失败?是因为系统调用是在内核模式下进行的吗?背后的原因是什么?
3 回答
我假设您在问为什么调用这些例程的代码会检查结果以确定是否发生错误。
您引用的每个例程socket
、fork
、 和malloc
,都需要资源。这些资源可能不可用,因为调用进程超出了系统管理员或用户设置的限制,或者因为系统已经耗尽了它拥有的资源并且无法为进程提供更多资源。因此,即使不频繁,对这些例程之一的调用也有可能返回失败。所以调用进程应该检查失败。
此外,在一些实现中,如果在操作完成之前将信号传递给进程,则可以中断一些系统例程(例如read
和)。write
(当一个信号到达时,它被认为是重要的,并且希望立即将它传递给进程而不是等待一个可能很长的操作完成。所以操作被中断,信号被传递,进程可能会处理信号并从信号处理程序返回。然后控制权返回到调用原始例程的代码,并且必须通知该代码操作已中断。)此中断导致返回失败,错误状态指示操作已中断。
总是,如果只是.. 回到当一个 C 函数只能返回一个整数,并且异常是科幻小说时,他们想出了返回成功或提供错误线索的代码的想法。它变成了一个约定。
取决于你所说的失败。
诸如打开文件之类的事情(考虑到开发人员可能会被打扰)相对容易处理,例如找不到文件。Malloc,采取一些补救措施有点困难。
关键点是尽可能靠近错误进行检查。如果你不这样做,你会发现你想要打开并附加到的文件在 10,000 行代码之后不存在,当你尝试将大量计算的结果写入它并说访问冲突时。
基本上,这些东西是发明异常的原因。检查返回值是“可选的”,吞下异常是明确的。
例子:
FILE *fp;
fp = fopen("c:\\removedDirectory\nonexistingFile.txt", "r")//returns NULL
if(fp != NULL)
{
//stuff here will fail if fp == NULL
}
如果不检查 fopen 的输出,(替换为任何返回错误的函数)并且fp
为 NULL,则依赖于真实文件流的后续函数将不起作用。