如何解决为什么sys.exit4294967295将%ERRORLEVEL%设置为-1?
在弄乱调用Python脚本的批处理脚本时偶然发现了这一点。
在Python脚本中,我正在调用sys.exit(-1)
,它将%ERRORLEVEL%
设置为4294967295。在读取Windows使用32位无符号整数之后,我将其更改为sys.exit(4294967295)
,但是现在%ERRORLEVEL%
是-1。
它为什么做逆运算? sys.exit(-1)
之所以有意义,是因为其(2 ^ 32)-1并与回绕一起存储,但是为什么使用32位无符号整数的最大值转换为-1?是C里面的东西吗?
解决方法
负整数值可以使用基数补码表示。因此,相同的基础四字节值0xFFFFFFFF可以表示无符号的32位值4294967295或有符号的32位two's complement值-1。这仅取决于如何在上下文中解释字节,这包括使用带符号对无符号指令,例如在x86 ISA中使用JG
(如果有更大符号,则跳转)与{{1} }(如果高于则跳-未签名)。
CMD等待进程退出时,它通过GetExitCodeProcess
获取退出状态,并将其保存为32位带符号整数JA
。 ( module_name!symbol_name 是调试器(例如windbg或cdb)如何在已加载的模块中引用全局符号名称的方法。)即使Windows在API级别返回,Windows仍将退出状态解释为带符号整数cmd!LastRetCode
,它是DWORD
的C typedef。
通常,Windows中的进程退出状态是一个无符号的16位值,范围为0-65535。通常是通过失败,即EXIT_SUCCESS
(0)或unsigned long
(1)。但是,如果Windows程序异常终止(例如未处理的异常),则状态码通常是EXIT_FAILURE
值,它是一个32位带符号整数,将警告和故障表示为负值。例如,访问冲突为NTSTATUS
(0xC0000005或-1073741819)。
当程序异常终止时,批处理脚本可能需要特殊处理。可以使用STATUS_ACCESS_VIOLATION
表达式测试最后的退出状态,如果最后的退出状态等于或大于指定的数字,则为true。例如:
errorlevel <number>
CMD本身具有特殊处理,可以为C:\>cmd /c exit -1073741819
C:\>if errorlevel 0 (echo normal exit) else (echo abnormal exit)
abnormal exit
打印“ ^ C”(0xC000013A或-1073741510),退出状态表示未处理的控制台控制事件,其中包括未处理的Ctrl + C(取消)和Ctrl +打破。例如:
STATUS_CONTROL_C_EXIT
除了C:\>cmd /c exit -1073741510
^C
检查外,CMD还具有内置的errorlevel
环境变量。内置环境变量实际上并没有存储在流程环境块中。它们作为默认值提供。在调试器中,您可以观察到CMD调用%ERRORLEVEL%
来获取环境变量的值。此函数首先尝试WinAPI cmd!GetEnvVar
,该API返回实际的过程环境变量(例如GetEnvironmentVariableW
)或操作系统内置变量之一(例如PATH
,__APPDIR__
)。如果__CD__
找不到“ ERRORLEVEL”,则GetEnvironmentVariableW
默认为内置值,即通过GetEnvVar
转换为字符串的LastRetCode
值,格式为字符串{{ 1}}(即带符号的十进制整数)。例如:
StringCchPrintfW
CMD还将最后一个退出状态设置为"%d"
(由于名称以“ =”开头,因此通常处于隐藏状态),该退出状态为无符号32位值,格式为填充零的十六进制数字。如果退出状态是可打印的ASCII序数,范围为32-126,则CMD还将设置C:\>cmd /c exit -1
C:\>echo %errorlevel%
-1
C:\>set errorlevel=foo
C:\>echo %errorlevel%
foo
。无论出于何种原因,CMD都将它们存储为真实环境变量,这些变量将由子进程继承。例如,对于退出状态为65(即0x41,即ASCII序数“ A”):
%=ExitCode%
关于Python中的%=ExitCodeAscii%
,请注意C:\>cmd /c exit 65
C:\>python -q
>>> import win32api
>>> win32api.GetEnvironmentVariable('=ExitCode')
'00000041'
>>> win32api.GetEnvironmentVariable('=ExitCodeAscii')
'A'
(及其下的sys.exit(4294967295)
)将退出状态作为已签名的Python整数处理,该整数被转换为C {{1} }的范围为-2147483648至2147483647。使用此范围之外的值将导致转换失败,并将退出状态设置为-1。请参阅在GitHub上发布的源代码中的_Py_HandleSystemExit
。碰巧4294967295(0xFFFFFFFF)是-1的二进制补码表示形式,但是对于任何其他不受支持的值,您将得到相同的结果。例如:
sys.exit(status)
正常退出状态是0表示成功,1表示失败,包括将错误消息打印到stderr时:
raise SystemExit(status)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。