失败时返回代码。积极还是消极?

时间:2017-11-13 13:39:10

标签: c linux return errno

在Linux中的特殊情况下,C程序无法执行。 示例:您分配了一些空间,操作系统拒绝了它。

char *buffer = (char *) malloc(1024);
if (buffer == NULL)
    return ENOMEM;

此故障由返回代码标记,该代码将传送到操作系统。

  • 返回代码0(EXIT_SUCCESS)被标记为成功执行。
  • 非0的返回码被标记为失败。

所以我的问题是,程序检测到错误时的约定是什么。 它应该返回正面还是负面的返回代码?

我的教授告诉我,无论如何在UNIX / Linux中都会返回一个负面的错误代码。但是errno-Codes都是正整数。 EXIT_FAILURE的define-Statement也是1,一个正整数。 我的代码应该是这样的:

char *buffer = (char *) malloc(1024);
if (buffer == NULL)
    return -ENOMEM;

或者喜欢上面的代码?我从Linux-Kernel-Modules了解到,在大多数情况下,它们会在失败时返回负错误代码。

感谢您的帮助。

6 个答案:

答案 0 :(得分:3)

  

所以我的问题是,当程序检测到时,常规是什么   错误。它应该返回正面还是负面的返回代码?

你没有做出这种选择的奢侈(或责任)。从C的角度来看,您的选择分为三类:

  • 您指定的退出状态为0EXIT_SUCCESS(不一定是不同的)。这表明成功完成。

  • 您指定的退出状态为EXIT_FAILURE。这表示完成失败。

  • 您指定的退出状态是其他任何内容。

在每种情况下,向主机环境发出信号的结果都是实现定义的,但在第一种情况下它是传达成功的结果,而在第二种情况下它是传递失败的结果。

现在,在Linux和其他实现POSIX exit()语义的操作系统上,实现定义已经标准化了:

  

状态的值可以是0EXIT_SUCCESSEXIT_FAILURE或任何其他值,但只有最低有效8位(即{{1} })应该来自status & 0377wait() ;

IEEE Std 1003.1-2008, 2016 Edition;重点补充)。这些是传统的UNIX语义;只有您指定的退出状态的最低8位才重要,因此签名将丢失。但是,当前版本的POSIX继续说:

  

可以从waitpid()waitid()传递给siginfo_t的信号处理程序获取完整值。

因此,如果知道要查找父进程,可以将负数传递给父进程。但总的来说,它不会这样做。特别是,如果父进程是shell,那么它就不会这样做。

  

我的教授告诉我,无论如何在UNIX / Linux中都会返回一个负面的错误代码。

这听起来更像是关于除SIGCHLD 以外的函数的函数返回码的指令,但我不明白为什么你认为我们对你教授的意思的第二次猜测会更多比直接要求你的教授澄清更可靠。

  

但是errno-Codes都是正整数。

那么,与你的教授澄清的另一件事就是他是否给你关于他如何期望你为他的班级编写职能的更具体的指示(更有可能),或者他是否在就一般的C或POSIX惯例作出断言(不太可能,因为有许多POSIX函数不是真的)或其他东西。

请注意,C标准库函数不会返回main()代码。当它们返回指示失败的代码(通常但不总是负数)时,程序员有义务查询errno变量的详细原因 - 函数返回代码通常不携带该信息。一些由POSIX标准化但不是C 的函数直接返回errno代码;显然,这些都不符合你教授的处方。

另请注意,errno值用于在同一程序调用的函数之间进行通信,而不是用于与程序环境进行通信。它们不打算用作程序退出状态,特别是,不能保证它们的值适合8位(见上文)。

  

EXIT_FAILURE的define-Statement也是1,一个正整数。我的代码应该是这样的:

errno的值取决于实现。因此,您只能从中收集特定于实现的洞察力。但是,正如您所看到的,通用退出状态表明您的实施中的程序失败是EXIT_FAILURE

在Linux和其他POSIX(-ish)系统上,通过选择1到125之间的故障状态,实现与shell的最佳集成,因为shell指定状态126-255的特殊意义,当然,解释状态0成功。

1
     

或者喜欢上面的代码?我从大多数Linux-Kernel-Modules中了解到这一点   在失败的情况下,他们会返回负的错误代码。

再一次,没有。 Errno代码不能用作程序退出代码,只有在相当特殊的情况下才能尝试退出负状态。一个常见的惯例是向char *buffer = (char *) malloc(1024); if (buffer == NULL) return -ENOMEM; 写一条信息性错误消息(stderr完全用于此目的),然后退出状态1或(更好,IMO)perror()

如果您想提供描述故障性质的退出代码,那么您需要在每个程序的基础上定义它们的值和重要性,记住为了获得最佳兼容性,您只需使用1到125个

答案 1 :(得分:2)

程序中未进一步指定的错误代码的约定是使用EXIT_FAILURE。它将被定义为操作系统识别为失败退出代码的值。

errno.h中定义的宏不是过程的返回码,而是仅用于程序执行期间的错误。标准库将它们放在全局errno中,如果您愿意,也可以将它们用作函数的返回码。其中三个由C标准指定:EDOMEILSEQERANGE。 POSIX指定了更多。不要将这些用作main()的返回码(或作为exit()的参数)。

答案 2 :(得分:1)

通常,Linux程序在成功时返回0,在失败时返回非零。有一些例外(例如grep,其值表示是否找到匹配项)。原因是bash提示符将true定义为0,将false定义为1,因此它使脚本编写变得简单:

somecmd && action "if succesful"

但这就是程序本身。对于程序内部的代码,通常会有各种约定。常见的是成功时返回0(或正值),或者失败时返回负值。这背后的原因是所有指令集(我都知道)有一个如果为零的分支,或者一个如果少于零的指令,这意味着它只有一条指令用于比较(如反对必须进行比较然后在比较匹配时进行分支。

答案 3 :(得分:1)

来自进程的UNIX / Linux上的退出代码return中的main()语句或对exit()的调用无符号< / em>的范围是0 - 255.

功能,它可以是您想要的任何类型。许多库函数在出错时返回-1

然而,这并不总是可行的,特别是通常返回指针的函数。按照惯例,这些函数会在出错时返回NULL,例如fopen()malloc()

这些返回代码仅表示发生了错误,而不是错误,通常(出错时)全局errno也设置为正错误代码,提供更多信息。见man errno

答案 4 :(得分:0)

errno是您将使用错误编号设置的全局变量。惯例是设置errno然后返回负数(通常为负数)。负返回值表示应检查errno。使用您的示例(并将其放入函数中),它可能如下所示:

int allocate_buffer(char *buffer) {
    buffer = malloc(1024);
    if (buffer == NULL) {
        errno = ENOMEM;
        return -1;
    }
    return 0;
}

然后调用者将根据返回值知道是否存在错误,并检查错误以查看错误是什么,并决定如何从那里继续。

答案 5 :(得分:-1)

5.1.2.2.3程序终止

  

如果main函数的返回类型是与int兼容的类型,   从初始调用到main函数的返回相当于   使用main返回的值调用exit函数   作为其论点; 11)到达终止的   main函数返回值0.如果返回类型不是   与int兼容,终止状态返回给主机   环境没有特别说明。

7.22.4.4退出功能:

  

最后,控制权返回给主机环境。如果值   status为零或EXIT_SUCCESS,一种实现定义的形式   状态成功终止返回。如果状态值是   EXIT_FAILURE,一种实现定义的状态形式   返回失败的终止。否则状态   返回是实现定义。

我发现这是自我描述的。