C++实现一个简单的异常日志记录类

NX12.0标准C++异常日志记录完整示例 在NX12.0开发过程中,当捕获到标准C++异常时,如何正确记录异常日志是关键。通过完善的try-catch机制与日志系统结合,能有效提升调试效率与稳定性,尤其针对nx12.0捕获到标准c++异常怎么办提供了实用解决方案。 阅读详情
 
头文件
#pragma once
/////////////////////////////////////////////////////////////////////////////////
//异常信息记录类

#include <string>
#ifdef UNICODE
#define tstring std::wstring
#else
#define tstring std::string
#endif

//定义异常信息结构体
typedef struct _EXCEPTION_INFO
{
	tstring tstrExceptionInfo;//异常信息字符串
	int     nExceptionLine;	//出现异常的代码行
}EXCEPTION_INFO,LPEXCEPTION_INFO;

//填充异常结构体
inline EXCEPTION_INFO FillExceptionInfo(TCHAR* pInfo,int nLine)
{
	EXCEPTION_INFO ei;
	ei.tstrExceptionInfo.append(pInfo);
	ei.nExceptionLine=nLine;
	return ei;
}

class _declspec(dllexport) CErrorLog
{
public:
	CErrorLog(TCHAR* pModuleName);
	virtual~ CErrorLog();
	//记录异常,参数依次为函数名、错误信息、模块名
	bool WriteErrorLog(tstring& tstrFuncName,int nLine,tstring& tstrErrorMsg=tstring(_T("")),tstring& tstrModuleName=tstring(_T("")));
	bool WriteErrorLog(TCHAR* pFuncName,int nLine,TCHAR* pErrorMsg=NULL,TCHAR* pModuleName=NULL);
protected:
	/********************受保护的成员函数**********************/
	//记录自身异常
	bool WriteOwerErrorLog( tstring& tstrFunName, tstring& tstrErrMsg,int nLine);
	bool WriteOwerErrorLog(TCHAR* strFuncName,TCHAR* pErrorMsg,int nLine);
	//格式化当前时间
	inline std::string FormatTime();
	//获取系统错误信息
	inline std::string FormatLastError();
private:
	//保存当前模块的名称
	tstring m_strModuleName;
};

实现

#include "stdafx.h"
#include "CodeConvert.h"
#include "ErrorLog.h"
#include <time.h>
#include <assert.h>

CErrorLog::CErrorLog(TCHAR* pModuleName)
{
	assert(pModuleName);
	m_strModuleName.append(pModuleName);
}
CErrorLog::~CErrorLog()
{

}
bool CErrorLog::WriteOwerErrorLog(TCHAR* pFuncName,TCHAR* pErrorMsg,int nLine)
{
	return WriteErrorLog(pFuncName,nLine,pErrorMsg,_T("CErrorLog"));
}

bool CErrorLog::WriteOwerErrorLog(tstring& tstrFunName, tstring& tstrErrMsg,int nLine )
{
	return WriteErrorLog(tstrFunName,nLine,tstrErrMsg,tstring(_T("CErrorLog")));
}

bool CErrorLog::WriteErrorLog(TCHAR* pFuncName,int nLine,TCHAR* pErrorMsg,TCHAR* pModuleName)
{
	bool bRet=true;
	try
	{
		assert(pFuncName);
		if(NULL!=pErrorMsg)
		{
			std::string strExcep;
			std::string strFuncName;
#ifdef UNICODE
			strFuncName.append(CCodeCovert::WcharToChar(pFuncName));
			strExcep.append(CCodeCovert::WcharToChar(pErrorMsg));
#else
			strFuncName.append(pFuncName);
			strExcep.append(pErrorMsg);
#endif
			TCHAR szPath[MAX_PATH+1]={0};
			GetModuleFileName(NULL,szPath,MAX_PATH);
			int nDes=-1;
			for(size_t i=0;i<_tcslen(szPath);++i)
			{
                if('\\'==szPath[i])
					nDes=i;
			}
			szPath[nDes+1]='\0';
			_tcscat(szPath,_T("ErrorLogs\\"));
			::CreateDirectory(szPath,NULL);
			if(NULL!=pModuleName)
			{
				_tcscat(szPath,pModuleName);
				_tcscat(szPath,_T(".log"));
			}
			else
			{
				tstring strTemp=m_strModuleName;
				strTemp.append(_T(".log"));
				_tcscat(szPath,strTemp.c_str());
			}
			FILE* fp=_tfopen(szPath,_T("a+"));
			char* pBuffer="*************************************************************************\n";
			int nRet=fwrite(pBuffer,strlen(pBuffer),1,fp);
			pBuffer="系统时间:";
			fwrite(pBuffer,strlen(pBuffer),1,fp);
			std::string strTime=FormatTime();
			//strTime.append("\n");
			fwrite(strTime.c_str(),strTime.size(),1,fp);
			pBuffer="文件路径:";
			fwrite(pBuffer,strlen(pBuffer),1,fp);
			char szSourcePath[MAX_PATH+2]={0};
			sprintf(szSourcePath,"%s\n",__FILE__);
			fwrite(szSourcePath,strlen(szSourcePath),1,fp);
			pBuffer="异常行数:";
			fwrite(pBuffer,strlen(pBuffer),1,fp);
			char szLine[7]={0};
			sprintf(szLine,"%d\r\n",nLine);
			fwrite(szLine,strlen(szLine),1,fp);
			pBuffer="异常函数:";
			fwrite(pBuffer,strlen(pBuffer),1,fp);
			strFuncName.append("\n");
			fwrite(strFuncName.c_str(),strFuncName.size(),1,fp);
			pBuffer="异常信息:";
			fwrite(pBuffer,strlen(pBuffer),1,fp);
			strExcep.append("\n");
			fwrite(strExcep.c_str(),strExcep.size(),1,fp);
			std::string strSyserror=FormatLastError();
			fwrite(strSyserror.c_str(),strSyserror.size(),1,fp);
			fclose(fp);
		}
	}
	catch(EXCEPTION_INFO& except)
	{
		bRet=false;
	    WriteOwerErrorLog(tstring(_T("WriteErrorLog")),except.tstrExceptionInfo,except.nExceptionLine);
	}
	return bRet;
}

bool CErrorLog::WriteErrorLog( tstring& tstrFuncName,int nLine,tstring& tstrErrorMsg/*=tstring(_T(""))*/,tstring& tstrModuleName/*=tstring(_T(""))*/ )
{
	return WriteErrorLog((TCHAR*)tstrFuncName.c_str(),nLine,(TCHAR*)tstrErrorMsg.c_str(),\
	   (TCHAR*)tstrModuleName.c_str());
}

std::string CErrorLog::FormatLastError()
{
	std::string strRet("系统错误:");
	try
	{
		LPVOID lpErrorMsg=NULL; 
		FormatMessage(
			FORMAT_MESSAGE_ALLOCATE_BUFFER | 
			FORMAT_MESSAGE_FROM_SYSTEM | 
			FORMAT_MESSAGE_IGNORE_INSERTS, 
			NULL, 
			GetLastError(), 
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language 
			(LPTSTR)&lpErrorMsg, 
			0, 
			NULL 
			);
		tstring tstrError((LPTSTR)lpErrorMsg);
#ifdef UNICODE
		std::string strError=CCodeCovert::WstringToString(tstrError);
		strRet+=strError;
#else
		strRet+=tstrError;
#endif
		::LocalFree(lpErrorMsg);
	}
	catch(TCHAR* pError)
	{
		WriteOwerErrorLog(_T("FormatLastError"),pError,__LINE__);
	}
	return strRet;
}
std::string CErrorLog::FormatTime()
{
	std::string strRet;
	try
	{
		tm* st;
		time_t time64=time(NULL);
		st=localtime(&time64);
		strRet.append(asctime(st));
	}
	catch(TCHAR* pError)
	{
	
		WriteOwerErrorLog(_T("FormatTime"),pError,__LINE__);
		strRet.clear();
	}
	return strRet;
}


 该类对基本的文件操作,错误信息获取,系统时间获取等进行了封装,使用的时候也是很简单的。

测试:

#include "stdafx.h"
#include <iostream>
#include "ErrorLog.h"
class CarBase:public CErrorLog
{
public:
	CarBase()
		:CErrorLog(_T("CarBase"))
	{



		 if(1)
			 WriteErrorLog(_T("CarBase"),__LINE__-1,_T("测试错误!!!!"));
	}
public:
	void Init()
	{
		CarBase();
	}
};
class Car:public CarBase
{

};
int _tmain(int argc, _TCHAR* argv[])
{
	CarBase cb;
	int nlen=0;
	nlen=sizeof(CarBase);
	std::cout<<"类CarBase的大小为:"<<nlen<<std::endl;
	for(int i=0;i<100;++i)
		cb.WriteErrorLog(_T("MAIN"),__LINE__,_T("不知道的问题"),_T("模块"));
	return 0;
/*	_onexit()*/
}

由于能力有限,欢迎批评指教。

 

C++程序崩溃之空指针异常调试指南 主动检查指针并在发现nullptr时抛出自定义异常,这样可以在上层通过try-catch块捕获。这需要显式地添加检查代码,但提供了结构化的错误处理方式。");// 安全解引用try {return 0;空指针异常是C++编程中常见的问题之一,但通过合理的预防措施和调试方法,我们可以有效地避免和处理它。在开发过程中,我们应该始终初始化指针变量,并在使用之前检查其是否为空。此外,还可以使用智能指针、断言、自定义异常等手段来提高代码的健壮性和可靠性。 阅读详情

相关推荐

基于log4cpp封装的日志记录类设计与实现

Log4cpp的日志级别用于标识日志信息的严重程度,通常按照优先级从低到高排列为:DEBUG < INFO < WARN < ERROR < FATAL。不同级别的日志适用于不同的场景,开发者可以根据需要选择合适的日志级别来控制输出内容。Log4cpp允许开发者通过继承类实现自定义的Appender,满足特定业务需求,如将日志发送到远程服务器、数据库或消息队列。通过的方法,可以灵活定制日志格式。例如以下格式字符串包含更丰富的信息:输出示例:格式符号含义%F。

weixin_42596246的博客 763

C++写错误日志函数

在编写程序,有些问题借助错误日志更好跟踪。 UNICODE代码: DWORD  WriteErrLog ( CString strError) { DWORD nWrite=0, bytesWritten; HANDLE hFile;     BOOL res;     CString strErrorLog, strTime ,strLogName; SYSTEMTIME d

shejiannan的专栏 3282

C++实现文件日志记录指南

本文还有配套的精品资源,点击获取 简介:在复杂系统开发和调试中,C++中的日志记录到文件是一项关键功能,它记录错误、异常和关键事件。本篇介绍如何从基础到高级实现C++文件日志记录功能,包括自定义日志级别、设计日志类、文件初始化和关闭、日志级别控制、多线程支持、日志旋转和格式化。同时,建议在实际项目中优先考虑使用成熟的日志库。 1. 日志系统概念介绍 日志系统...

weixin_28872035的博客 1824

C语言记录程序日志

我们写程序,不可能一次就写的一个bug都没有,必须要不停地修改,有可能自己调试已经没有问题了,发给客户后还是问题很多,这个时候跑到客户处解决问题就不现实了,自己不在还要找到问题的所在,最好的办法就是记录一下程序运行的日志了,只需要跟客户要下日志文件,自己就能定位错误的大概地方了,好提供更改的数据支持。

腹有诗词气自华 1637

深入解析cpp_trace开源日志记录库

cpp_trace是一个为C++开发者提供的高效、灵活、轻量级的日志记录库。它通过其精心设计的API,使得开发者在任何阶段,无论是开发、测试还是生产环境,都能够方便地集成和使用日志记录功能。在接下来的章节中,我们将探讨cpp_trace如何提供这些功能,以及它如何成为日志记录的优选解决方案。创建一个自定义过滤器涉及继承cpp_trace库提供的Filter类,并重写其should_log方法。在该方法中,开发者可以定义自己的逻辑来返回一个布尔值,指示是否应该记录一条消息。

weixin_36019375的博客 1217

C++ 日志记录库开源实现与实践

日志级别是控制日志输出详细程度的工具,它允许开发者按照重要性对日志消息进行分类。DEBUG,INFO,WARNING,ERROR,CRITICAL在Log.h中,我们定义了五种日志级别:DEBUGINFOWARNINGERRORCRITICAL。这些级别不仅用于控制日志的输出,还可以作为过滤条件,来决定日志消息是否被写入到日志文件或控制台中。在日志记录实践中,日志级别是控制日志信息的重要机制,它允许开发者根据信息的紧急程度和重要性过滤日志。C++中常见的标准日志级别包括。

weixin_36059856的博客 1197

C++异常

异常是一种程序控制机制,与函数机制独立和互补  函数 是一种以 栈结构 展开的上下函数衔接的程序控制系统,异常 是另一种控制结构,它依附于栈结构,却可以同时设置多个异常类型作为网捕条件,从而以类型匹配在栈机制中 跳跃回馈 1)C++的异常处理机制使得异常的引发和异常的处理不必在同一个函数中,这 样底层的函数可以着重解决具体问题,而不必过多的考虑异常的处理。上层调 用者可以再适当的位置设计对不同类型异常的处理。  2)异常是专门针对抽象编程中的一系列错误处理的,C++中不能借助函数机 制,因为栈结构的本质

log_Li的博客 130

纯C++实现跨平台日志记录系统

POSIX(Portable Operating System Interface)标准起源于1980年代初,其目的是为了提高UNIX系统间的可移植性和兼容性。IEEE(电气和电子工程师协会)负责维护POSIX标准,并通过一系列文档描述了系统API和系统调用,使得开发人员能够在不同的UNIX系统之间轻松迁移程序。POSIX标准的意义在于:提高软件的可移植性:遵循POSIX标准编写的程序可以在任何支持该标准的操作系统上运行,这包括Linux、各种BSD、Solaris等。统一API标准。

weixin_36059856的博客 1107

c/c++ 在catch住错误后写入日志文件,加上函数名,所在文件,所在行号

void testFunction() { printf("%s/n %s/n %d/n",__FUNCTION__,__FILE__,__LINE__); } int _tmain(int argc, _TCHAR* argv[]) { testFunction(); printf("%s/n",__FUNCTION__); getchar(); return 0; } 呵呵,还是挺有用的。

kongjiajie的专栏 1407

C++高效日志类设计与实现

在软件开发中,日志记录是跟踪和诊断应用程序行为的重要手段。自定义日志目录提供了一种灵活的方式来组织和管理这些日志文件,以便于维护和分析。下面我们将深入探讨日志目录的创建和配置,以及如何实现日志文件的动态管理策略。SysLog.h头文件是SysLog.cpp文件的接口部分,通常它会声明用于发送日志消息的函数和类。它可能包括了日志级别枚举、日志消息的发送函数原型等,也可能包含一些预处理器指令,用于控制日志记录的开关或调整日志记录的配置。// 定义日志级别LOG_DEBUG,LOG_INFO,

weixin_35094083的博客 716

C++ 错误日志 所在函数 所在行

本程序利用自带宏,实现历史纪录,错误日志代码,可以保存指定文件位置所在函数,行数等信息。已测试过,可以运行

日志包装器

虽然现在有许多成熟的日志工具可供选用,但是自己编写一个日志类可以让你用得更加得心应手。对于抛出异常的处理,C++语言本身并没有做什么东西,可怜的STL也只有一个很简单的异常类,所以下面先给出一个最简单的Exception类。 Exception.h #ifndef _EXCEPTION_H_ #define _EXCEPTION_H_ #include class Exception

Terry关注智能硬件创业 596

从USB 2.0到USB 3.x:Synopsys SVT USB VIP配置避坑与接口选择指南

本文详细解析了从USB 2.0到USB 3.x的Synopsys SVT USB VIP配置要点,涵盖协议版本选择、物理接口匹配及UVM层次化架构实现。重点介绍了layering sequence的配置技巧和常见问题解决方案,帮助验证工程师高效避坑并优化验证流程。

weixin_42653691的博客 238

分享个C++日志记录类以及日志记录程序

前言 个人觉得开发中比较重要的一点就是“不要重复发明轮子”,现在国外、国内开源软件遍地开花,尤其是Google,开源了一系列性能、架构特别好的代码,如果能够用开源的应该尽量避免自己造轮子。那么为什么不用log4plus呢?在这里我需要的是一个简单实用、轻巧的日志记录程序,log4plus对我有点臃肿,所以才自己花店时间写了一个简单的日志记录类。 日志类实现 刚开始想的是为了避免大量的读写程序

https://github.com/JelinYao 1万+

一文入门Qwen-Agent【附实战代码】

Qwen-Agent 是一个开源框架,用于开发基于 Qwen 模型的 AI 智能体应用,一文带你入门使用

m0_55303420的博客 1873

SAP 物料主数据 Forecasting 视图,别把预测只当成一个数字字段

摘要(150字): SAP S/4HANA物料主数据的Forecasting视图常被忽视,但对依赖历史消耗规律的物料至关重要。该功能基于工厂维度的历史消耗数据,结合预测参数自动计算未来需求,动态调整重订货点和安全库存。预测模板(Forecast Profile)能标准化参数设置,而消耗数据(Consumption Values)的质量直接影响预测结果。预测值作为MRP输入,需注意保存操作才能生效。自动重订货点功能通过分析消耗波动和服务水平,实现库存策略的动态优化。Individual Forecast功能则

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1432

C++日志记录类

工作几年后,发现自己从来不写博客,不是一个好习惯。往往总结的东西不记录下来,下次再来用时,总感觉疲态百出。所以吧,是该总结总结一点东西了。进入正题吧! 很多程序员不太注重日志记录,其实不是一个好的习惯。有些人觉得用DebugViewer就可以查看一些打印信息了,写日志有什么用呢? 但是,当我们发布的产品给用户使用时,出现异常时如何处理呢?难道需要远程TeamViewer去用DebugViewer...

cs821984831的博客 1360

零基础入门simulink仿真建模--通信领域的编码与纠错技术--基于Simulink的CRC校验算法仿真建模示例

CRC是一种广泛应用于数字网络和存储设备中的错误检测码。它的基本原理是利用除法运算来产生固定长度的校验位,这些校验位被附加到原始数据之后发送出去。接收端收到数据后,重新计算校验值并与接收到的校验值进行比较,如果两者相同,则认为数据没有错误;否则,表示数据可能已被损坏。发送端:随机比特生成模块 + CRC生成模块。信道:模拟数据传输过程中的潜在错误(可选)。接收端:CRC校验模块 + 错误指示模块。通过本指南,我们介绍了如何基于Simulink搭建一个简单的CRC校验系统模型,并进行了仿真分析。

amy_mhd的博客 727

Qt-异常捕获以及日志记录

Qt中的异常捕获以及Qt捕获不到异常现象的原因及解决方案,日志的接入及使用方法。

qq_48498725的博客 7564

CKA-题库-简洁参考答案-反复练习20遍-必过!!!

新版CKA考试已于2020年9月1日正式上线! 考试模式:线上考试 考试时间:2小时 认证有效期:3年 软件版本:Kubernetes v1.19 重考政策:可接受1次重考 经验水平:中級 题目数量:17题 题库量小:随机的题目重复率极高 考试时可打开两个浏览器Tab,一个是考试窗口,一个用来查阅官方文档](https://kubernetes.io/docs/) 01 Task - 英文 Create a new ClusterRole named deployment-clusterrole tha.

随笔记录-分享&记忆 7315

ARM交叉编译gdbserver并远程在线调试

arm-linux平台。5、生成完整的makefile,新建full_install,执行 ./configure --target=arm-linux-gnueabihf --host=arm-linux-gnueabihf --program-prefix=arm-linux-gnueabihf- CC=arm-linux-gnueabihf-gcc --prefix=/home/geyuxi/Documents/full_install。如果--host和--build不同,是交叉编译;

wangjie36的博客 3168

C++中如何处理线程函数抛出的异常

C++中如何处理线程函数抛出的异常

qqrrjj2011的博客 1407

thinkphp6/8 - 实现评论区发表评论、回复评论功能数据库表设计与整个逻辑思路过程分析,tp5 评论盖楼等功能(附带源码稍加改造即可使用)

tp5评论区数据库表设计,tp5发表回复评论功能设计,thinkphp5如何做评论功能,tp5 php评论区实现发表回复删除评论,tp5评论区盖楼源码及数据表设计思路,thinkphp评论功能详细教程,thinkphp实现评论与回复功能,thinkphp实现文章评论和回复评论功能,tp5实现评论回复功能,thinkphp如何实现评论区,tp5网站PC移动端h5怎么做评论区发表留言及回复功能,thinkphp实现评论区插件,thinkphp评论区相互发表回复功能详细教程,thinkphp有没有评论区的组件插件

✅ 精选推荐文章 3159
上一篇: 使用开源库zlib压缩和解压文件
下一篇: 两道C语言面试题
疯狂-的-蜗牛
博客等级 码龄16年 427粉丝 104原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值