天道酬勤,学无止境

How can D return 0 on success and non-zero on failure if main is void?

In D, the main function is defined:

void main(/*perhaps some args but I do not remember*/)
{

}  

I know for sure that this function returns zero on success and non-zero on failure and yet it is defined as not returning anything. What is the logic behind it?

标签

评论

What Alexandrescu is saying is simply shorthand for the exit code I described. The zero or nonzero returned to the OS is a (language-agnostic) process exit code, not a function return value. The OS doesn't call main directly, and main doesn't return directly to the OS. The D compiler inserts startup and shutdown code in your program to handle these interactions with the OS, as do pretty much all other compilers for other languages. On startup, for instance, this boilerplate code uses some OS-dependent mechanism to get the command-line arguments, and puts them into a D string[] array to pass to main. On shutdown, it uses the return value from int main for the exit code, or, for void main, uses its own value (0 for success, nonzero for unhandled exception).

In pseudocode:

// Generated by compiler
void _realMain()
{
    // OS-dependent; probably calls GetCommandLineW
    // and CommandLineToArgvW on Windows, for example
    string[] cmdLineArgs = createArgArray();

    int exitCode = 0;    // Assume success
    try
    {
        // static if selects only one call to main for compilation,
        // depending on main's return type.

        // If main has been written to return int, use its value for the exit code
        static if (main returns int)
            exitCode = main(cmdLineArgs);
        // If main has been declared void, just run it and keep the exit code of 0
        else
            // void main: *doesn't return anything*
            main(cmdLineArgs);
    }
    catch
    {
        // Unhandled exception results in non-zero exit code
        exitCode = 1;
        printStackTrace();
    }

    // OS-dependent process shutdown function.
    // This is where the exit code is "returned" to the OS.
    // Note it *does not* use the return keyword to do so.
    // Calling the OS's function to kill the current process
    // does not return, because the process is dead by the
    // time the function has finished!
    exitProcess(exitCode);
    // In particular, no code *after* the exitProcess line will run.
}

There are several possible signatures for main():

void main()
void main(string[] args)
void main(char[][] args)
void main(wstring[] args)
void main(wchar[][] args)
void main(dstring[] args)
void main(dchar[][] args)
int main()
int main(string[] args)
int main(char[][] args)
int main(wstring[] args)
int main(wchar[][] args)
int main(dstring[] args)
int main(dchar[][] args)

If int is the return type, then it's pretty much the same is in C or C++. The value that you return is what the OS/shell sees. If an exception is thrown, then a stack trace is printed, and the OS/shell sees a non-zero value. I don't know what it is. It may vary by exception type.

If void is the return type, then the OS/shell sees 0. If an exception is thrown, then a stack trace is printed, and the OS sees a non-zero value. Again, I don't know what it is.

Essentially, having void main allows you to not worry about returning a value to the OS/shell. Many programs are not in the least bit concerned with returning success or failure to the OS/shell. So, with void, the OS/shell always gets 0 unless an exception is thrown - which makes sense, since the only program failure at that point is if an exception escapes main(). If you do care about returning success or failure to the OS/shell, then you simply use one of the versions that returns int.

The plethora of signatures due to different string types is that you can use pretty much any of the possible string types as the input to main(). main() and main(string[] args) are probably the most commonly used though.

function with void return type does not return any value. There is nothing illogical when you consider call stack looks like this:

OS -> D runtime -> main

The main function is invoked by D runtime system, which recognized that the main function returns nothing - and in this case return success to the OS. In case the main function is defined with return type int, then the D runtime return to OS value returned by main function.

If you define the function as

int main(...);

then the return value, that you can get (in bash) using

echo $?

will be whatever you return from the function. If you don't return anything, or you define your main function as

void main(...);

then the exit status of the command is undefined. For some reason (I can't find any documentation on this) it's always 200 on my system.

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 达内C语言UnixC(DAY02)
    动态库(共享库) 动态库和静态库最大的不同就是,链接动态库并不需要将库中的被调用代码复制到调用模块中, 相反被嵌入到调用模块中的仅仅是被用代码在动态库中的相对地址。 在调用模块实际运行时,再根据动态库的加载地址和被调用代码的相对地址去计算出该代码的绝对地址 读取代码的内容,并运行之。 如果动态库中的代码同时被多个进程所用,动态库的实例在内存中仅需一份,因此动态库也叫共享库。 使用动态库占用的内存空间小,即使修改了动态库中的代码,只要其相对地址不变,无需重新链接。 因为在执行过程中,需要计算被调用代码的绝对地址,以及一些附带的额外开销,所以调用动态库会 比调用静态库略慢一些动态库形式:libxxx.so构建动态库: 编译选项:-fpic,位置无关代码 链接选项:-shared,没有main函数的可执行程序链接动态库 gcc … lxxx -L<库路径> … gcc … lxxx <—— LIBRARY_PATH调用动态库:运行时需要调用动态库中的代码,因此动态库必须位于LD_LIBRARY_PATH环境变量所表示的某个路径下 代码:shared/ 因为相较于静态库而言,动态库具有明显的优势,因此gcc的链接器缺省使用动态库版本 如果一定要使用静态库版本参与链接,需要加上-static链接选项。 代码:hello.c 动态库的动态加载
  • 如果抛出异常,则使用非零代码退出 spring-batch 作业(Make a spring-batch job exit with non-zero code if an exception is thrown)
    问题 我正在尝试修复从 shell 脚本启动的 spring-batch 作业。 然后脚本检查进程退出代码以确定作业是否成功。 但是,即使程序以异常结束,Java 也会退出 0,除非 System.exit 是用不同的代码专门调用的,因此脚本总是报告成功。 有没有办法让 spring-batch 在失败时返回非零代码? 需要明确的是,我不是在谈论 ExitStatus 或 BatchStatus,而是在谈论 java 进程的实际退出代码。 如果无法告诉 spring-batch 返回非零值,我可以安全地在 Tasklet(或侦听器)中使用 System.exit 而不会干扰 spring-batch 在异常后所做的任何事情? 如果做不到这一点,任何人都可以提出一种方法来将 BatchStatus 或其他一些失败指标返回给 shell 脚本吗? 回答1 我不建议从 tasklet 调用 System.exit(),因为作业不会完全完成,因此 BATCH_-Tables 中的某些条目可能会处于不一致的状态。 如果使用类 CommandLineJobRunner 来启动批处理,则返回根据 BatchStatus 的返回代码(CommandLineJobRunner 可以配置为 SystemExiter;默认情况下,它使用 JvmSystemExiter 在最后调用 System.exit
  • 为什么shell中的0为true,但false为1?(Why 0 is true but false is 1 in the shell?)
    问题 false; echo $? 上面将输出1 ,这与我所知道的所有其他编程语言相矛盾。 有什么原因吗? 回答1 这是一个约定,但考虑到它特别有用。 通常,如果程序成功,这就是您所需要知道的。 但是,如果失败,则可能需要了解有关失败的所有信息,包括失败的原因,修复方法等。零均值表示“成功”而非零均值表示故障使您可以轻松地检查是否成功,并根据需要调查特定错误以获取更多详细信息。 许多API和框架都有类似的约定-成功的函数返回0,而失败的函数返回描述特定失败情况的错误代码。 回答2 Bash是一种编程(脚本)语言,但它还是一种外壳程序和一个用户界面。 如果0是错误,则程序只能显示一种错误。 但是在Bash中,任何非零值都是错误,我们可以使用1-255之间的任何数字来表示错误。 这意味着我们可以有很多不同类型的错误。 1是一般错误, 126表示无法执行文件, 127表示“未找到命令”,等等。这是带有特殊含义的Bash退出代码列表,其中显示了一些最常见的退出代码。 成功也有很多种(退出状态为0 )。 但是,成功将使您可以继续进行下一步-您可以将结果打印到屏幕上或执行命令等。 回答3 这里有两个相关的问题。 首先,OP的问题,为什么shell中的0为true,而false为1? 第二,为什么应用程序成功返回0,失败返回非零? 要回答OP的问题,我们需要了解第二个问题。
  • C中的main()函数(main() function in C)
    问题 我已经以自学成才的方式学习C编程已有几周了,关于main()函数还有一些问题。 所有函数必须在其函数原型中声明,然后在其定义中声明。 为什么我们不必首先在原型中声明main()函数? 为什么我们必须使用int main()而不是void main() ? 在main()函数中,返回0到底是做什么的? 如果我编写了一个以return 1;结束main()函数的程序,会发生什么? , 例如? 回答1 仅在使用函数之前需要声明函数。 该定义本身就是一个声明,因此不需要任何先前的原型。 (如果在没有先验原型的情况下定义了函数,则某些编译器和其他工具可能会发出警告。这仅是作为有用的指南,而不是C语言的规则。) 因为C标准是这样说的。 操作系统将返回值传递给调用程序(通常是外壳程序)。 一些编译器将接受void main ,但这是非标准扩展(通常意味着“始终向操作系统返回零”)。 按照惯例,非零返回值表示发生了错误。 Shell脚本和其他程序可以使用它来确定您的程序是否成功终止。 回答2 1)所有函数必须在其函数原型中声明,然后在其定义中声明。 为什么我们不必首先在原型中声明main()函数? 不对。 简单的例子: void foo(){} //definition int main() { foo(); return 0; } 仅当调用了一个函数但尚未看到定义时,才需要声明。
  • HaaS EDU K1设备资源 之 IIC
    1、概述 IIC(Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。 I2C总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。 开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。 结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。 应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。IIC总线如图所示: IIC总线时序图 2、资源介绍 HaaS1000中自带了两路I2C,只支持主模式,最高1.4Mbps接口。两路I2C管脚也是复用的,都是通过IO的fuction选择出来的。 当前的EDU的默认配置为: 引脚名 GPIO 说明 I2C_M0_SCL GPIO_P2_0 i2C0的SCL I2C_M0_SDA GPIO_P2_1 i2C0的SDA I2C_M1
  • 在 C 和 C++ 中 return 0 的意义是什么? [复制](What is the significance of return 0 in C and C++? [duplicate])
    问题 这个问题在这里已经有了答案: main() 在 C 和 C++ 中应该返回什么? (18 个回答) 7年前关闭。 我需要最简单的答案。 我在各种网站上查找了答案。 如果程序的输入是输出为 10,命令返回 0 是否会强制程序返回值 0 而不是 10? 我在 Borland IDE 上编写了简单的 C 程序而没有返回 0,它们运行良好。 回答1 没有什么可添加到 Maroun 的链接中的。 如果您想了解有关返回值的更多信息,这就是方法。 给新手说几句: int main() { return 0; } 和 int main() { return 22; } 和 void main() { } 如果您不检查程序的返回值并在大多数默认设置的编译器上编译,则所有行为都将相同。 当您在命令行 (windows) 或 shell (linux) 上执行程序时,您可以通过检查返回值来检查该程序是否失败或成功完成其任务,即您正在返回的值。 顺便说一句,遵循标准是一个好习惯,因此我强烈推荐给您。 回答2 main 函数通常应该返回一个值,并在它返回某些内容后完成执行。返回 0 表示成功,返回非零数字表示失败。 因此,我们在主函数结束时“返回 0”。 但是你可以在不返回 0 的情况下运行 main 函数。它的工作原理是一样的。 来源:main 的正确声明是什么? 回答3
  • 使用exit()函数(Use of exit() function)
    问题 我想知道如何以及何时可以像本书中的程序一样使用exit()函数: #include<stdio.h> void main() { int goals; printf("enter number of goals scored"); scanf("%d",&goals); if(goals<=5) goto sos; else { printf("hehe"); exit( ); } sos: printf("to err is human"); } 当我运行它时,它显示错误:调用未定义的函数exit() 。 另外,我想知道如何创建一个选项来关闭程序运行所在的窗口? 例如,我制作了一个菜单驱动程序,其中包含多个选项,其中一个选项是“退出菜单” 。 我该如何退出程序(即关闭窗口)? 回答1 尝试使用exit(0); 反而。 退出函数需要一个整数参数。 并且不要忘记#include <stdlib.h> 。 回答2 exit函数在stdlib标头中声明,因此您需要 #include <stdlib.h> 在程序的顶部,可以使用exit 。 还要注意exit具有一个整数参数,因此您不能像exit()那样调用它,而必须以exit(0)或exit(42)调用。 0通常表示您的程序成功完成,并且非零值用作错误代码。 还有预定义的宏EXIT_SUCCESS和EXIT_FAILURE
  • Jenkins 通过或失败构建外部可执行文件(Jenkins pass or fail build on external executable)
    问题 作为构建过程的一部分,我编写了一个 EXE,用于将数据库更改推送到暂存数据库。 这个过程有时会遇到错误,如果是这样,我希望构建失败。 如何将 EXE 添加为构建步骤,以便在失败时(我可以将其作为异常捕获)我可以使构建失败并记录一些详细信息(类似于 NUIt 显示失败的方式)? 我还希望 exe 记录一些其他详细信息(例如更改的内容 - 构建通过还是失败)。 是否有任何文档可以说明如何执行此操作? 我正在使用 MSBuild,我可以完全控制 EXE(我写的)。 我可以编码以输出我想要的 回答1 您在主要构建步骤中使用什么? 马文? 蚂蚁? 自定义脚本? 有很多方法可以做到这一点,这在很大程度上取决于您的 .exe 的设计方式,您没有在 OP 中解释。 最简单的方法是从下拉列表中添加另一个构建步骤。 选择执行 Windows 批处理命令。 在那里,编写批处理命令以启动 .exe 并捕获返回代码: C:\Location_of_exe\your.exe IF NOT "%ERRORLEVEL%" == "0" ( ECHO "Your exe failed" EXIT /B 1 ) ELSE ( ECHO "Your exe passed" ) 如果您的 .exe 像普通程序一样工作,它会在成功时返回退出代码 0,否则它将返回一个非零退出代码。 上面的语句查找非零退出代码
  • 仅在测试通过时提交git(Commit in git only if tests pass)
    问题 我最近开始使用git,还开始了单元测试(使用Python的unittest模块)。 我想在每次提交时都运行测试,并且仅在测试通过时才提交。 我猜想我需要在/hooks使用pre-commit ,并且已经设法使其在测试中运行,但是如果它们的测试失败,我似乎找不到停止提交的方法。 我正在使用make test运行测试,而make test又正在运行python3.1 foo.py --test 。 无论测试通过还是失败,似乎我都没有得到不同的退出条件,但是我可能在错误的地方寻找。 编辑:这是我想在这里做的罕见事吗? 我本以为这是一个普遍的要求... Edit2:以防万一人们无法打扰阅读注释,问题在于unittest.TextTestRunner不会以非零状态退出,无论测试套件是否成功。 为了做到这一点,我做到了: result = runner.run(allTests) if not result.wasSuccessful(): sys.exit(1) 回答1 我将检查以确保执行脚本的每个步骤在失败时都返回非零退出代码。 如果测试失败,请检查python3.1 foo.py --test返回非零退出代码。 检查以确保您的make test命令返回非零退出代码。 最后,检查您的pre-commit钩子本身在失败时是否返回非零退出代码。 您可以通过添加|| echo $
  • Linux 进程间通信方式(管道、命名管道、消息队列、信号量、共享内存、套接字)
    什么是进程? 在Linux系统中,进程是管理事务的基本的过程。进程拥有自己独立的处理环境和系统资源。进程整个生命可以简单划分为三种状态: 就绪态: 进程已经具备执行的一切条件,正在等待分配CPU的处理时间。 执行态: 该进程正在占用CPU运行。 等待态: 进程因不具备某些执行条件而暂时无法执行的状态。 进程间通信概念 进程是一个独立的资源分配单元,不同进行之间的资源是独立的,不能在一个进程中直接访问另一个进程的资源。所以不同的进程需要进行信息的交互状态的传递等,因此需要进程间通信。LINUX常见的进程间通信如下: 1.管道 2.命名管道 3.消息队列 4.信号量 5.共享内存 6.套接字 1~5都是同一个主机进程间通信。序号6是不同主机(网络)进程间通信; 管道 管道又称无名管道。是一种古老的IPC通信形式,管道的作用正如其名,需要通信的两个进程在管道的两端;管道是一种特殊类型的文件,存在于内核的缓冲区。管道有如下的特点: 1.半双工,数据不能在两段上传数据,数据只能在一个方向流动。 2.管道不是普通的文件,不属于某个文件系统,只存在于内存中。 3.管道没有名字,只能在亲缘关系的父子进程之间通信。 pid_t fork(void); fork()函数得到的子进程是父进程的复制品,它从父进程处继承了整个进程的地址空间。 返回值 当成功完成时,fork()将返回0给子进程
  • HaaS EDU K1设备资源 之 SPI
    1、概述 SPI, Serial Perripheral Interface, 串行外围设备接口, 是 Motorola 公司推出的一种同步串行接口技术. SPI 总线在物理上是通过接在外围设备微控制器(PICmicro) 上面的微处理控制单元 (MCU) 上叫作同步串行端口(Synchronous Serial Port) 的模块(Module)来实现的, 它允许 MCU 以全双工的同步串行方式, 与各种外围设备进行高速数据通信. SPI 主要应用在 EEPROM, Flash, 实时时钟(RTC), 数模转换器(ADC), 数字信号处理器(DSP) 以及数字信号解码器之间. 它在芯片中只占用四根管脚 (Pin) 用来控制以及数据传输, 节约了芯片的 pin 数目, 同时为 PCB 在布局上节省了空间. 正是出于这种简单易用的特性, 现在越来越多的芯片上都集成了 SPI技术。 CPOL与CPHA CPOL与CPHA是SPI中一个非常重要的概念。其分别代表SPI的极性Polarity和相位Phase: (1) CKPOL (Clock Polarity) = CPOL = POL = Polarity = (时钟)极性 (2) CKPHA (Clock Phase) = CPHA = PHA = Phase = (时钟)相位 CPOL和CPHA,分别都可以是0或时1
  • C语言小知识:C语言函数返回 1 和返回 0 究竟哪个好!你知道吗?
    基本上,没有人会将大段的C语言代码全部塞入 main() 函数。更好的做法是按照复用率高、耦合性低的原则,尽可能的将代码拆分不同的功能模块,并封装成函数。 C语言代码的组合千变万化,因此函数的功能可能会比较复杂,不同的输入,常常产生不同的输出结果。 C语言函数的返回值 C语言函数可以通过返回值表示输出结果,例如 log() 函数的返回值会根据不同的输入,返回不同的值。 再比如,我们定义一个函数 myopen(),用于打开某个文件,那么,这个函数要么能够成功打开文件,要么打开文件失败,这时,可以通过返回值区分“成功”和“失败”。 当然,myopen() 函数失败的原因可能很多,但不是本文关注的重点,本文更关心的是,该以何值表示“成功”,何值表示“失败”。 按照C语言语法, 0 表示假,非零(常常用 1)表示真,那是否函数也用 0 返回值表示“失败”,1 返回值表示“成功”呢? C语言“ 潜规则” C语言函数当然可以使用返回值 0 表示“失败”,用返回值 1 表示“成功”。 事实上,C语言函数用什么样的返回值表示成功或者失败,只是一种人为的约定,函数的调用者遵守这个“约定”就可以了。 C语言也有“行业潜规则”, 不过,对于一般的函数,大多数C语言程序员常常使用返回值 0 表示成功,非零值表示失败。 因此,如果希望我们定义的函数能够被大多数人愉快的使用,最好不要反其道而行,遵守
  • Linux网络编程笔记9 | 多线程
    十四、多线程 1.什么是线程? 源代码 -编译和链接-> 程序 -加载到内存中-> 进程 | | 文件 内存 / \ 代码 <- 执行 数据 <- 处理 | | <- CPU 静态 动态 | | 资源 线程 线程就是进程的执行过程,即进程内部的控制序列,或者说是进程中的一个任务。 一个进程可以同时拥有多个线程,即同时被系统调度的多个执行路径,但至少要有一个主线程——main函数及被其调用的其它函数。 一个进程的所有线程都共享进程的代码区、数据区、BSS区、堆区、环境变量和命令行参数区、文件描述符表、信号处理函数、当前工作目录、用户和组的各种ID等。但是栈区不是共享的,一个进程的每个线程都拥有自己独立的栈区。 线程调度: 1)系统内核中专门负责线程调度的处理单元被称为调度器; 2)调度器将所有处于就绪状态(没有阻塞在任何系统调用上)的线程排成一个队列,即所谓就绪队列; 3)调度器从 就绪队列中获取队首线程,为其分配一个时间片,并令处理器执行该线程,过了一段时间: A.该线程的时间片耗尽,调度器立即终止该线程,并将其排到就绪队列的尾端,接着从队首获取下一个线程; B.该线程的时间片未耗尽,但需阻塞于某系统调用,比如等待I/O或者睡眠。调度器会中止该线程,并将其从就绪队列中移至等待队列,直到其等待的条件满足后,再被移回就绪队列; 4)在低优先级线程执行期间,有高优先级线程就绪
  • LInux 网络编程笔记5 | 进程
    十、进程 1.进程的基本概念 程序:磁盘上的可执行文件。 | 加载 v 进程:内存中的指令和数据。 执行 | ^ v | 访问 CPU---+ 2.进程的分类 交互式进程:由Shell启动,借助标准I/O与用户交互。 批处理进程:在无需人工干预的条件下,自动运行一组批量任务。 守护(精灵)进程:后台服务,多数时候处于待命状态,一旦有需要可被激活完成特定的任务。 3.进程快照 ps - :显示当前用户拥有控制终端的进程信息 ps axuw - BSD风格选项 a: 所有用户 x: 既包括有控制终端也包括无控制终端的进程 u: 详细信息 w: 更大列宽 ps -efFl - SVR4风格选项 e: 所有用户的所有进程 f: 完整格式 F: 更完整格式 l: 长格式 USER/UID: 进程的实际用户ID PID: 进程标识 %CPU/C: CPU使用率 %MEM: 内存使用率 VSZ: 占用虚拟内存大小(KB) RSS: 占用半导体物理内存大小(KB) TTY: 终端次设备号 ttyn - 物理终端(硬件设备) pts/n - 虚拟终端(软件窗口) ? - 无控制终端,如后台进程 STAT/S: 进程状态 O - 就绪,等待被调度 R - 运行,Linux下没有O状态,就绪状态也用R表示 S - 可唤醒睡眠,系统中断,获得资源,收到信号, 都可被唤醒,转入运行状态 D -
  • Perl:成功的系统调用后,“ or die”命令仍会结束脚本(Perl: After a successful system call, “or die” command still ends script)
    问题 我正在使用以下行进行有效的简单系统调用: system ("mkdir -p Purged") or die "Failed to mkdir." ; 执行脚本确实可以进行系统调用,我可以找到一个名为Purged的目录,但是错误消息仍会打印并且脚本消失。 我的语法有什么问题? 回答1 这有点令人困惑,不是吗? 莱昂纳多·埃雷拉(Leonardo Herrera)关于池上的答案 是的,在Perl中, system命令会反转true和false,并创建如下有趣的逻辑,这令人困惑: if ( system qw($command) ) { die qq(Aw... If failed); } else { say qq(Hooray! It worked!); } 但是,为什么system命令可以执行此操作是可以理解的。 在Unix中,退出状态为零表示程序正常运行,而非零状态可以为您提供信息,说明system调用失败的原因。 也许您正在调用的程序不存在。 也许程序按预期工作了。 例如,当grep工作时, grep返回退出代码1 ,但是没有匹配的行。 您可能想区分grep何时返回零,一或返回码大于一。 (是的,我知道在Perl程序中使用系统调用grep是很愚蠢的,但这是我想到的第一个示例)。 为了防止偶然的混乱,我创建了一个变量来保存我的system命令的退出状态
  • JVM:java 可执行文件的退出代码是如何定义的?(JVM: how are exit codes of the java executable defined?)
    问题 我正在寻找java可执行文件的可能退出代码的定义: (如何)我可以判断退出代码是执行的 Java 进程还是 VM 本身的代码? 示例:在 Windows 上, java -badoption返回1 ; 以Main为有效类的java Main也可能返回1 。 我可以使用任何 VM 选项来使退出代码更有意义吗? 例如区分两种类型的退出代码? 如果我知道退出代码不是来自我的 Java 进程(仅返回0 ),非零退出代码是什么意思? 在 Windows 上,我经常看到-1和1 。 由于这些是通过自动错误报告工具报告的,因此我看不到任何错误消息。 我只有退出代码,需要解释它。 退出代码是否依赖于平台? 回答1 退出代码的含义(一般) ISO/IEC 9899(编程语言:C)、ISO/IEC 9945(IEEE 1003、POSIX) 没有什么是专门为 Java / JVM 定义的。 这些退出代码的含义由 ISO/IEC 9899(编程语言:C,例如 7.20.4.3 ISO/IEC 9899:TC3 的exit函数)、ISO/IEC 9945(IEEE 1003、POSIX)和类似规范定义,它总是这样: 0 表示成功任何其他值都意味着失败 shell 环境( sh 、 bash 、 cmd.exe 、 make等)使用它来确定程序是成功退出(0)还是出现错误(不是 0)。 强烈建议仅使用
  • 批处理goto丢失错误级别(Batch goto loses errorlevel)
    问题 考虑以下蝙蝠test.bat(PC01已关闭): mkdir \\PC01\\c$\Test || goto :eof 如果我从命令外壳运行该蝙蝠: > test.bat || echo 99 > if ERRORLEVEL 1 echo 55 输出仅为55。否99。有一个错误级别,但|| 操作员没有看到它。 如果我使用cmd /c -运行蝙蝠cmd /c - > cmd /c test.bat || echo 99 > if ERRORLEVEL 1 echo 55 输出为空白。 错误级别为0。 如果我删除|| goto :eof || goto :eof ,一切都按|| goto :eof ,即输出为 99 55 有谁知道为什么发生这种半生半熟的ERRORLEVEL行为? 回答1 在大多数情况下,|| 是检测错误的最可靠方法。 但是您偶然发现了ERRORLEVEL起作用但||很少见的情况之一。 才不是。 问题源于以下事实:您的错误是在批处理脚本中引发的,并且|| 响应最近执行的命令的返回码。 您将test.bat视为单个“命令”,但实际上它是一系列命令。 在脚本中执行的最后一个命令是GOTO :EOF ,并且该命令成功执行。 因此,您的test.bat||echo 99响应GOTO :EOF的成功。 当您从脚本中删除||GOTO :EOF ,您的test.bat|
  • Bash - 查找 exec 返回值(Bash - find exec return value)
    问题 我需要一种方法来判断 grep 是否确实找到了某些东西,并且最好将该返回值传递给 if 语句。 假设我有一个tmp文件夹(当前文件夹),其中有几个文件和子文件夹。 我想在所有名为abc文件中搜索模式xyz 。 如果找到任何出现的xyz (无论xyz被找到多少次都无关紧要),则假定搜索是成功的。 如果未找到xyz则搜索失败。 在 bash 中,它可以这样完成: find . -name "abc" -exec grep "xyz" {} \; 这将显示是否找到了xyz 。 但我不确定如何将结果(成功与否)传递回if语句。 任何帮助,将不胜感激。 回答1 你可以试试 x=`find . -name abc | xargs grep xyz` echo $x 也就是说, x 包含您的返回值。 不匹配时为空白。 回答2 如果您想知道find找到了一些文件abc并且其中至少一个包含字符串xyz ,那么您可能可以使用: if find . -name 'abc' -type f -exec grep -q xyz {} + then : All invocations of grep found at least one xyz and nothing else failed else : One or more invocations of grep failed to find
  • system() 的退出代码不符合预期(Exit Codes from system() not as expected)
    问题 system() 函数似乎返回了我从它调用的进程中获得的退出代码的 128 倍。 从手册页: 返回值 错误时返回的值为 -1(例如,fork(2) 失败),否则返回命令的状态。 这是我所拥有的。 $ ls tinker.c tinker.c $ echo $? 0 $ ls notexisting ls: cannot access notexisting: No such file or directory $ echo $? 2 $ cat tinker.c #include <stdio.h> #include <stdlib.h> int main(void) { printf("%d\n", system("ls tinker.c")); printf("%d\n", system("ls notexisting")); return 0; } $ gcc tinker.c -o tinker $ ./tinker tinker.c 0 ls: cannot access notexisting: No such file or directory 512 第一次调用表明我没有失败,但返回代码看起来与我从手册页中读取的内容完全不同。 我做错了什么? 回答1 从 POSIX 系统(3): 如果 command 不是空指针,则 system() 应以 waitpid()
  • 应用程序应支持哪些“标准”应用程序返回/退出代码?(What “standard” application return/exit codes should an application support?)
    问题 是否有一组标准的应用程序返回代码? 诸如成功返回 0 失败返回 1 之类的事情? 我有一个 Windows Server 应用程序,我正在添加一些返回错误代码,并且除了我需要的特定于应用程序的代码之外,还希望坚持使用标准代码。 回答1 没有应用程序应该遵守的标准退出代码集。 但是,正如您提到的,有一些常见的成功,例如 0。 根据您使用的操作系统和工具,您或许可以查看类似应用程序的退出代码并模仿它们。 回答2 我认为唯一的标准是成功为 0,失败为非零。 这更像是一种约定而不是标准。 回答3 也许您可以采用一些 Unix 约定。 在另一个答案中,用户 David 建议 sysexits.h有一个标准退出代码列表。 它似乎至少可以追溯到 1993 年,一些像 Postfix 这样的大项目使用它,所以我想这是要走的路。 从 OpenBSD 手册页: 根据 style(9),在结束程序时使用任意值调用 exit(3) 来指示失败条件并不是一个好习惯。 相反,应该使用来自 sysexits 的预定义退出代码,这样进程的调用者可以在不查看源代码的情况下粗略估计故障类别。 这是在 Debian 系统上显示的列表: #define EX_USAGE 64 /* command line usage error */ #define EX_DATAERR 65 /* data format