WIN32错误知识补充
通过《Win32 Error》、《COM Error---HRESULT》和《NTSTATUS》等我们知道了一些win32错误基础知识,下面我们说点其他的东西。
1、GetLastError()返回一个winapi错误代码.从1开始的简单数字.它们通常从底层本机api错误代码映射。Winapi错误代码在WinError.h SDK头文件中声明.您可以指望使用FORMAT_MESSAGE_FROM_SYSTEM选项从FormatMessage()获取描述性字符串。
2、HRESULT是COM错误代码.它由三个基本部分构成,高位表示严重性,中间位编码指示错误源的工具,低16位编码错误编号.HRESULT_FROM_WIN32()宏是一个帮助宏,用于将winapi错误代码映射到COM错误代码.它只将严重性设置为"失败",设施代码设置为7(winapi)并将错误代码复制到低位.有许多可能的COM错误代码,并且只有少数可以通过FormatMessage()转换为字符串.您应该使用ISupportErrorInfo接口来询问COM服务器是否可以通过IErrorInfo提供错误的描述。
3、内核和Native API则一般使用NTSTATUS类型的错误码。它们记录在ntstatus.h SDK标头中.winapi应该包装原生api。FormatMessage()可以将常用的转换为字符串,只要它不是驱动程序生成的自定义错误代码即可.有几种api使用这些错误代码,即使它们在用户模式下运行,获取此类错误代码的字符串需要使用FormatMessage和FORMAT_MESSAGE_FROM_HMODULE选项。
另外,这三者之间是可以相互转换的:
GetLastError->HRESULT: HRESULT_FROM_WIN32
NTSTATUS -> Win32:LsaNtStatusToWinError()
NTSTATUS -> HRESULT:HRESULT_FROM_WIN32( LsaNtStatusToWinError())
还有其他一些全局的函数可以帮到我们:
名称 | 说明 |
---|---|
AtlHresultFromLastError | 以 HRESULT 的形式返回 GetLastError 错误代码。 |
AtlHresultFromWin32 | 将 Win32 错误代码转换为 HRESULT。 |
AtlReportError | 设置 IErrorInfo 可向客户端提供错误详细信息。 |
AtlThrow | 引发 CAtlException 。 |
AtlThrowLastWin32 | 调用此函数可根据 Windows 函数 GetLastError 的结果发出错误。 |
关于异常DBG_TERMINATE_PROCESS(0x40010004)
简介
DBG_TERMINATE_PROCESS表示进程被调试器终止。值为0x40010004。其定义如下:
//
// MessageId: DBG_TERMINATE_PROCESS
//
// MessageText:
//
// Debugger terminated process.
//
#define DBG_TERMINATE_PROCESS ((NTSTATUS)0x40010004L) // winnt
说明
当调试器附加到应用程序然后终止它时,将出现此退出代码。
实际上,最有可能是由于系统关闭。 Windows关闭时,它将尝试正常退出正在运行的程序。如果它们拒绝退出,它们可能会被系统以退出代码
0x40010004
终止。例如,如果您有一个显示模式对话框的GUI程序,然后尝试关闭系统,则系统将提示您 xy.exe阻止了关闭。如果单击强制关闭,则该进程将被退出,退出代码为 0x40010004
。
这时软件拿到的是 ExitCode 是 1073807364 (0x40010004) 这个值相当于 -1073741510 (0xc000013a) 表示应用程序是在系统关闭的时候关闭,或者软件收到了 ctrl+C 或 ctrl+Break 关闭。
Windbg提示:*** WARNING: Unable to verify checksum for 的处理
当我们用windbg调试时,经常会遇到“*** WARNING: Unable to verify checksum for xxx.dll”这样的提示,他的意思时不能校验某某模块的校验和。这一般都是我们的动态库或exe的校验和没有设置。可以做如下两种处理:
1、在VS里修改配置,重新生成
2、使用VC工具包中的editbin工具可以为程序文件增加校验和
判断线程栈爆掉的一种方法
就是TEB::StackBase-TEB::StackLimit的值约为线程栈保留大小(VC++编译器默认的是1M),就可以判断栈 爆掉了。
比如:
!teb
TEB at 01192000
ExceptionList: 0120134c
StackBase: 01300000
StackLimit: 01201000
SubSystemTib: 00000000
FiberData: 00001e00
ArbitraryUserPointer: 00000000
Self: 01192000
EnvironmentPointer: 00000000
ClientId: 00004b7c . 000059d4
RpcHandle: 00000000
Tls Storage: 1a17b928
PEB Address: 0118f000
LastErrorValue: 0
LastStatusValue: c0000034
Count Owned Locks: 0
HardErrorMode: 0
?StackBase-StackLimit=01300000-01201000=1044480B=1020K加上保护页4K,就是1024K=1M了。
又比如:
0:000> !teb
TEB at 002bf000
ExceptionList: 001cfd78
StackBase: 001d0000
StackLimit: 000d1000
SubSystemTib: 00000000
FiberData: 00001e00
ArbitraryUserPointer: 00000000
Self: 002bf000
EnvironmentPointer: 00000000
ClientId: 00002d60 . 000044e4
RpcHandle: 00000000
Tls Storage: 0069d808
PEB Address: 002bc000
LastErrorValue: 0
LastStatusValue: 0
Count Owned Locks: 0
HardErrorMode: 0
?StackBase-StackLimit==001d0000-000d1000=1020K加上保护页4K,也是1024K=1M了。
Linux 之 .bashrc 文件作用
Linux 系统中很多 shell,包括bash,sh,zsh,dash 和 korn 等,不管哪种 shell 都会有一个 .bashrc
的隐藏文件,它就相当于 shell 的配置文件。
一般会有多个 .bashrc
文件,使用 find
命令可以查看:
$ sudo find / -name .bashrc /home/hj/.bashrc # hj 为用户名/root/.bashrc /snap/core18/941/etc/skel/.bashrc /snap/core18/941/root/.bashrc /snap/core18/970/etc/skel/.bashrc /snap/core18/970/root/.bashrc /snap/core/6818/etc/skel/.bashrc /snap/core/6818/root/.bashrc /snap/core/6964/etc/skel/.bashrc /snap/core/6964/root/.bashrc /snap/core/6673/etc/skel/.bashrc /snap/core/6673/root/.bashrc /etc/skel/.bashrc
不同目录下的 .bashrc
文件其作用不尽相同,比如:
/etc/skel/.bashrc
:文件将复制到系统上创建的任何新用户的主文件夹中/home/hj/.bashrc
:是bash
的配置文件,保存个人的一些个性化设置,如命令别名、路径等
在这里我们主要来探讨下用户主目录下的 .bashrc
文件,即:/home/hj/.bashrc
。
使用 man bash
命令查看到的联机帮助文件中的相关解释如下:
这个文件主要保存个人的一些个性化设置,如命令别名、路径等。下面是个例子:
.bashrc - The individual per-interactive-shell startup file.
这个文件主要保存个人的一些个性化设置,如命令别名、路径等。下面是个例子:
# User specific aliases and functionsPATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin".GBK export PATH LANG alias rm='rm -i'alias ls='/bin/ls -F --color=tty --show-control-chars'....
利用 .bashrc 进行个性化设置
每次修改 .bashrc
后,使用 source ~/.bashrc
(或者 . ~/.bashrc
)就可以立刻加载修改后的设置,使之生效。
一般会在.bash_profile
文件中显式调用.bashrc
。登陆 linux
启动 bash
时首先会去读取 ~/.bash_profile
文件,这样 ~/.bashrc
也就得到执行了,你的个性化设置也就生效了。
利用这一特性,可以实现一些个性化设置,如:Linux 系统开机执行自动某个脚本文件等,这在自动化运维方面有一定的用处。
1、修改 /home/hj/.bashrc
文件:
sudo vim /home/hj/.bashrc# 在最后添加两句后保存echo '这句话开机就会启动' # 打印输出python3 /home/hj/test.py # 执行 test.py 这个脚本
2、当 Linux 开机后:
可以看到 Linux 开机后加载了 .bashrc
文件。