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

Gromacs实战:从蛋白质-小分子对接到分子动力学模拟全流程解析

本文详细解析了使用Gromacs进行蛋白质-小分子复合物分子动力学模拟的全流程。从处理AutoDock等对接软件的结果文件开始,逐步指导如何为蛋白质和小分子分别生成拓扑文件,并解决力场合并的核心挑战。文章涵盖了构建模拟盒子、添加溶剂离子、能量最小化、平衡模拟以及关键的轨迹分析步骤,为计算生物学和药物设计研究者提供了一套从静态对接到动态评估的完整实战指南。

weixin_29251337的博客 1218

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

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

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

CocosCreator视频播放黑屏?手把手教你封装VideoPlayer组件解决Web环境问题

本文针对Cocos Creator在Web环境下视频播放黑屏等常见问题,提供了一套工程化的VideoPlayer组件封装解决方案。文章深入剖析了浏览器自动播放策略、DOM样式隔离等核心挑战,并手把手教你实现一个健壮的管理器,涵盖兼容性处理、性能优化与内存管理,确保视频播放稳定流畅。

plum99的博客 598

codesys【modbusRTU】主站

【代码】modbusRTU【codesys】

cfqq1989的博客 4371

C++日志记录类

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

cs821984831的博客 1360

Excel基金净值自动更新:手把手教你用Power Query抓取天天基金网数据(含常见错误修复)

本文详细介绍了如何利用Excel内置的Power Query工具,从天天基金网自动抓取基金净值数据,实现表格数据的自动刷新。通过手把手教程,您将学会构建参数化查询、整合多基金数据、计算持仓盈亏,并解决网页结构变动等常见错误,最终打造一个专属的、可自动更新的基金监控仪表盘,彻底告别手动更新。

xx56789的博客 728

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

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

qq_48498725的博客 7564

一文掌握SourceTree使用(超级详细)

SourceTree是一款开源的代码仓库客户端工具,界面美观,操作简单,具有代码克隆、本地创建、提交代码、撤销修改,拉取(pull)代码、上传(push)代码、合并分支等操作。对于软件开发人员是一款必备的应用软件。

GM_115的博客 3万+

SAP SD POD 配置与 VLPOD 操作:3步解决发货10件开票7件的业务场景

本文详细解析了SAP SD POD功能在解决发货与开票数量差异中的应用,通过3步配置法实现精准匹配。重点介绍了POD核心逻辑、关键配置步骤及VLPOD操作技巧,帮助企业高效处理易损品运输等复杂场景,提升供应链管理效率。

weixin_30613343的博客 393

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

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

qqrrjj2011的博客 1407

智慧加油站小程序数据库设计文档

【代码】智慧加油站小程序数据库设计文档。

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

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值