C++异常处理、Dump文件、断言、静态断言、日志文件
一、异常
__FILE__, __LINE__, __FUNCTION__, __DATE__, __TIME__
这几个宏可以用于异常抛出(输出文件、代码所在行、函数名、时间等),std::source_location
(C++20)也可以用来表示代码的信息(文件名,行号等)
头文件:cerrno、csignal、stdexcept system_error
1. dump文件生成
程序崩溃时,通过生成dump文件,可以定位到程序崩溃的原因。
windows:
MiniDumpWriteDump:程序崩溃时生成dump文件
SetUnhandledExceptionFilter:设置异常捕获函数,可以用来在程序崩溃时写日志。
linux:
设置ulimit -c [kbytes] 例如:ulimit -c 200
设置生成core文件的大小为200k
signal信号:可以用来在程序崩溃时写文件,比如将当前程序运行时的系统信息等写入文件
2. strerror的用法
#include <iostream>
//#include <cerrno>
//#include <cstring>
int main()
{
auto fp = fopen("file.txt", "r");
if (fp == NULL)
{
printf("Error: %s\n", strerror(errno));
}
return 0;
}
3. throw和catch的类型不一致
可以在宏定义里面对参数进行再一次的加工
#include <iostream>
#include <exception>
#include <string>
using namespace std;
#define ThrowError(Error) throw(Error.message)
class Error
{
public:
Error(string _file, string _fun, string _method, string _message)
:file(_file),
fun(_fun),
method(_method),
message(_message)
{}
string file;
string fun;
string method;
string message;
};
int main()
{
try
{
ThrowError(Error("file", "fun", "method", "An error"));
}
catch (string s)
{
cout << s << endl;
}
return 0;
}
二、assert断言
1. 普通断言
assert只有在 Debug 版本中才有效,如果编译为 Release 版本则被忽略
#include <cassert>
int main()
{
assert(1 > 2); //在debug模式下,抛出异常,控制台打印断言所在文件,所在代码行,以及源代码
}
assert其实就相当于if()else
#include <iostream>
#include <cassert>
void myAssert(bool expression)
{
if (!expression)
{
//...
abort();
}
}
int main()
{
myAssert(0);
}
2. 静态断言static_assert
可以在编译期发现更多的错误,用编译器来强制保证一些契约,帮助我们改善编译信息的可读性,尤其是用于模板时。
使用方式
static_assert(常量表达式,"提示字符串")
如果第一个参数常量表达式的值为false,会产生一条编译错误。错误位置就是该static_assert语句所在行,第二个参数就是错误提示字符串。
模板
编译器在遇到一个static_assert语句时,通常立刻将其第一个参数作为常量表达式进行演算。但如果该常量表达式依赖于某些模板参数,则延迟到模板实例化时再进行演算,这就让检查模板参数也成为了可能。
要求
static_assert的断言表达式的结果必须是在编译时期可以计算的表达式,即必须是常量表达式。
性能
由于static_assert是编译期间断言,不生成目标代码,因此static_assert不会造成任何运行期性能损失。
static_assert(1 > 0, "No error has occurred!");
static_assert(1 < 0, "An error has occurred!"); //编译不通过,VS会在错误列表栏显示一个错误
C++17支持静态断言只有一个参数static_assert(常量表达式)
3.自定义断言
可以用try{}catch(){}
,归根结底还是对if()else
的使用。
三、日志
1. spdlog:
-
非常快
-
只包含头文件
-
无需依赖第三方库
-
支持跨平台 - Linux / Windows on 32 / 64 bits
-
支持多线程
-
可对日志文件进行循环输出
-
可每日生成日志文件
-
支持控制台日志输出
-
可选的异步日志
-
支持日志输出级别
-
可自定义日志格式