├── .gitignore ├── Crash.sln ├── Crash ├── BaseException.cpp ├── BaseException.h ├── Crash.vcproj ├── StackWalker.cpp ├── StackWalker.h └── main.cpp ├── LICENSE └── ReadMe.md /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | 56 | # StyleCop 57 | StyleCopReport.xml 58 | 59 | # Files built by Visual Studio 60 | *_i.c 61 | *_p.c 62 | *_i.h 63 | *.ilk 64 | *.meta 65 | *.obj 66 | *.iobj 67 | *.pch 68 | *.pdb 69 | *.ipdb 70 | *.pgc 71 | *.pgd 72 | *.rsp 73 | *.sbr 74 | *.tlb 75 | *.tli 76 | *.tlh 77 | *.tmp 78 | *.tmp_proj 79 | *.log 80 | *.vspscc 81 | *.vssscc 82 | .builds 83 | *.pidb 84 | *.svclog 85 | *.scc 86 | 87 | # Chutzpah Test files 88 | _Chutzpah* 89 | 90 | # Visual C++ cache files 91 | ipch/ 92 | *.aps 93 | *.ncb 94 | *.opendb 95 | *.opensdf 96 | *.sdf 97 | *.cachefile 98 | *.VC.db 99 | *.VC.VC.opendb 100 | 101 | # Visual Studio profiler 102 | *.psess 103 | *.vsp 104 | *.vspx 105 | *.sap 106 | 107 | # Visual Studio Trace Files 108 | *.e2e 109 | 110 | # TFS 2012 Local Workspace 111 | $tf/ 112 | 113 | # Guidance Automation Toolkit 114 | *.gpState 115 | 116 | # ReSharper is a .NET coding add-in 117 | _ReSharper*/ 118 | *.[Rr]e[Ss]harper 119 | *.DotSettings.user 120 | 121 | # JustCode is a .NET coding add-in 122 | .JustCode 123 | 124 | # TeamCity is a build add-in 125 | _TeamCity* 126 | 127 | # DotCover is a Code Coverage Tool 128 | *.dotCover 129 | 130 | # AxoCover is a Code Coverage Tool 131 | .axoCover/* 132 | !.axoCover/settings.json 133 | 134 | # Visual Studio code coverage results 135 | *.coverage 136 | *.coveragexml 137 | 138 | # NCrunch 139 | _NCrunch_* 140 | .*crunch*.local.xml 141 | nCrunchTemp_* 142 | 143 | # MightyMoose 144 | *.mm.* 145 | AutoTest.Net/ 146 | 147 | # Web workbench (sass) 148 | .sass-cache/ 149 | 150 | # Installshield output folder 151 | [Ee]xpress/ 152 | 153 | # DocProject is a documentation generator add-in 154 | DocProject/buildhelp/ 155 | DocProject/Help/*.HxT 156 | DocProject/Help/*.HxC 157 | DocProject/Help/*.hhc 158 | DocProject/Help/*.hhk 159 | DocProject/Help/*.hhp 160 | DocProject/Help/Html2 161 | DocProject/Help/html 162 | 163 | # Click-Once directory 164 | publish/ 165 | 166 | # Publish Web Output 167 | *.[Pp]ublish.xml 168 | *.azurePubxml 169 | # Note: Comment the next line if you want to checkin your web deploy settings, 170 | # but database connection strings (with potential passwords) will be unencrypted 171 | *.pubxml 172 | *.publishproj 173 | 174 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 175 | # checkin your Azure Web App publish settings, but sensitive information contained 176 | # in these scripts will be unencrypted 177 | PublishScripts/ 178 | 179 | # NuGet Packages 180 | *.nupkg 181 | # The packages folder can be ignored because of Package Restore 182 | **/[Pp]ackages/* 183 | # except build/, which is used as an MSBuild target. 184 | !**/[Pp]ackages/build/ 185 | # Uncomment if necessary however generally it will be regenerated when needed 186 | #!**/[Pp]ackages/repositories.config 187 | # NuGet v3's project.json files produces more ignorable files 188 | *.nuget.props 189 | *.nuget.targets 190 | 191 | # Microsoft Azure Build Output 192 | csx/ 193 | *.build.csdef 194 | 195 | # Microsoft Azure Emulator 196 | ecf/ 197 | rcf/ 198 | 199 | # Windows Store app package directories and files 200 | AppPackages/ 201 | BundleArtifacts/ 202 | Package.StoreAssociation.xml 203 | _pkginfo.txt 204 | *.appx 205 | 206 | # Visual Studio cache files 207 | # files ending in .cache can be ignored 208 | *.[Cc]ache 209 | # but keep track of directories ending in .cache 210 | !*.[Cc]ache/ 211 | 212 | # Others 213 | ClientBin/ 214 | ~$* 215 | *~ 216 | *.dbmdl 217 | *.dbproj.schemaview 218 | *.jfm 219 | *.pfx 220 | *.publishsettings 221 | orleans.codegen.cs 222 | 223 | # Including strong name files can present a security risk 224 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 225 | #*.snk 226 | 227 | # Since there are multiple workflows, uncomment next line to ignore bower_components 228 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 229 | #bower_components/ 230 | 231 | # RIA/Silverlight projects 232 | Generated_Code/ 233 | 234 | # Backup & report files from converting an old project file 235 | # to a newer Visual Studio version. Backup files are not needed, 236 | # because we have git ;-) 237 | _UpgradeReport_Files/ 238 | Backup*/ 239 | UpgradeLog*.XML 240 | UpgradeLog*.htm 241 | ServiceFabricBackup/ 242 | *.rptproj.bak 243 | 244 | # SQL Server files 245 | *.mdf 246 | *.ldf 247 | *.ndf 248 | 249 | # Business Intelligence projects 250 | *.rdl.data 251 | *.bim.layout 252 | *.bim_*.settings 253 | *.rptproj.rsuser 254 | 255 | # Microsoft Fakes 256 | FakesAssemblies/ 257 | 258 | # GhostDoc plugin setting file 259 | *.GhostDoc.xml 260 | 261 | # Node.js Tools for Visual Studio 262 | .ntvs_analysis.dat 263 | node_modules/ 264 | 265 | # Visual Studio 6 build log 266 | *.plg 267 | 268 | # Visual Studio 6 workspace options file 269 | *.opt 270 | 271 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 272 | *.vbw 273 | 274 | # Visual Studio LightSwitch build output 275 | **/*.HTMLClient/GeneratedArtifacts 276 | **/*.DesktopClient/GeneratedArtifacts 277 | **/*.DesktopClient/ModelManifest.xml 278 | **/*.Server/GeneratedArtifacts 279 | **/*.Server/ModelManifest.xml 280 | _Pvt_Extensions 281 | 282 | # Paket dependency manager 283 | .paket/paket.exe 284 | paket-files/ 285 | 286 | # FAKE - F# Make 287 | .fake/ 288 | 289 | # JetBrains Rider 290 | .idea/ 291 | *.sln.iml 292 | 293 | # CodeRush 294 | .cr/ 295 | 296 | # Python Tools for Visual Studio (PTVS) 297 | __pycache__/ 298 | *.pyc 299 | 300 | # Cake - Uncomment if you are using it 301 | # tools/** 302 | # !tools/packages.config 303 | 304 | # Tabs Studio 305 | *.tss 306 | 307 | # Telerik's JustMock configuration file 308 | *.jmconfig 309 | 310 | # BizTalk build output 311 | *.btp.cs 312 | *.btm.cs 313 | *.odx.cs 314 | *.xsd.cs 315 | 316 | # OpenCover UI analysis results 317 | OpenCover/ 318 | 319 | # Azure Stream Analytics local run output 320 | ASALocalRun/ 321 | 322 | # MSBuild Binary and Structured Log 323 | *.binlog 324 | 325 | # NVidia Nsight GPU debugger configuration file 326 | *.nvuser 327 | 328 | # MFractors (Xamarin productivity tool) working folder 329 | .mfractor/ -------------------------------------------------------------------------------- /Crash.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Crash", "Crash\Crash.vcproj", "{BE2ADA3E-6638-401E-A52F-E56DC38C08CA}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {BE2ADA3E-6638-401E-A52F-E56DC38C08CA}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {BE2ADA3E-6638-401E-A52F-E56DC38C08CA}.Debug|Win32.Build.0 = Debug|Win32 14 | {BE2ADA3E-6638-401E-A52F-E56DC38C08CA}.Release|Win32.ActiveCfg = Release|Win32 15 | {BE2ADA3E-6638-401E-A52F-E56DC38C08CA}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /Crash/BaseException.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aMonst/RptCrash/cde05c5f19441e50dbae3393aea2fede06a339d3/Crash/BaseException.cpp -------------------------------------------------------------------------------- /Crash/BaseException.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "stackwalker.h" 3 | #include 4 | 5 | class CBaseException : public CStackWalker 6 | { 7 | public: 8 | CBaseException(HANDLE hProcess = GetCurrentProcess(), WORD wPID = GetCurrentProcessId(), LPCTSTR lpSymbolPath = NULL, PEXCEPTION_POINTERS pEp = NULL); 9 | ~CBaseException(void); 10 | virtual void OutputString(LPCTSTR lpszFormat, ...); 11 | virtual void ShowLoadModules(); 12 | virtual void ShowCallstack(HANDLE hThread = GetCurrentThread(), const CONTEXT* context = NULL); 13 | virtual void ShowExceptionResoult(DWORD dwExceptionCode); 14 | virtual BOOL GetLogicalAddress(PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD& offset ); 15 | virtual void ShowRegistorInformation(PCONTEXT pCtx); 16 | virtual void ShowExceptionInformation(); 17 | static LONG WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo); 18 | static void STF(unsigned int ui, PEXCEPTION_POINTERS pEp); 19 | protected: 20 | PEXCEPTION_POINTERS m_pEp; 21 | }; 22 | 23 | #define SET_DEFULTER_HANDLER() SetUnhandledExceptionFilter(CBaseException::UnhandledExceptionFilter) 24 | 25 | #define SET_DEFAUL_EXCEPTION() _set_se_translator(CBaseException::STF) -------------------------------------------------------------------------------- /Crash/Crash.vcproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aMonst/RptCrash/cde05c5f19441e50dbae3393aea2fede06a339d3/Crash/Crash.vcproj -------------------------------------------------------------------------------- /Crash/StackWalker.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aMonst/RptCrash/cde05c5f19441e50dbae3393aea2fede06a339d3/Crash/StackWalker.cpp -------------------------------------------------------------------------------- /Crash/StackWalker.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aMonst/RptCrash/cde05c5f19441e50dbae3393aea2fede06a339d3/Crash/StackWalker.h -------------------------------------------------------------------------------- /Crash/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "BaseException.h" 4 | 5 | void Func5() 6 | { 7 | CBaseException sw; 8 | sw.ShowCallstack(); 9 | } 10 | 11 | void Func4() 12 | { 13 | Func5(); 14 | } 15 | void Func3() 16 | { 17 | Func4(); 18 | } 19 | void Func2() 20 | { 21 | Func3(); 22 | } 23 | void Func1() 24 | { 25 | Func2(); 26 | } 27 | 28 | void StackWalkTest() 29 | { 30 | Func1(); 31 | } 32 | 33 | void ExceptionTest() 34 | { 35 | int i = 1; 36 | int c = i / 0; 37 | } 38 | 39 | void TryTest() 40 | { 41 | try 42 | { 43 | SET_DEFAUL_EXCEPTION(); 44 | int *p = NULL; 45 | *p = 0; 46 | } 47 | catch (CBaseException &e) 48 | { 49 | e.ShowExceptionInformation(); 50 | } 51 | } 52 | int _tmain(int argc, TCHAR* argv[]) 53 | { 54 | SET_DEFULTER_HANDLER(); 55 | CBaseException be; 56 | be.ShowLoadModules(); 57 | StackWalkTest(); 58 | TryTest(); 59 | 60 | ExceptionTest(); 61 | return 0; 62 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 aMonst 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | VC++ 程序崩溃日志记录 2 | ============================ 3 | 4 | 该程序主要在程序崩溃时获取程序崩溃位置的寄存器和堆栈信息并记录到日志中 5 | 使用方式非常简单,只需要将MSJExceptionHandler.h 和 MSJExceptionHandler.cpp放入源码工程中,编译即可。 6 | 由于它定义了全局变量,所以原始程序不需要做任何修改,不需要使用#include来包含。 7 | 日志最终被记录到生成的EXE同级目录的.rpt文件中,直接使用记事本打开即可看到效果 8 | 9 | main.cpp中提供一个简单的触发崩溃的条件 10 | 最终产生的文件内容大致如下: 11 | ``` 12 | //===================================================== 13 | //===================================================== 14 | Exception code: C0000005 ACCESS_VIOLATION 15 | Fault address: 00F31588 02:00000588 e:\Program\Crash\Debug\Crash.exe 16 | 17 | Registers: 18 | EAX:00000000 19 | EBX:7EFDE000 20 | ECX:00000000 21 | EDX:00000001 22 | ESI:00000000 23 | EDI:003CFC20 24 | CS:EIP:0023:00F31588 25 | SS:ESP:002B:003CFB48 EBP:003CFC20 26 | DS:002B ES:002B FS:0053 GS:002B 27 | Flags:00010212 28 | 29 | Call stack: 30 | Address Frame Logical addr Module 31 | 00F31588 003CFC20 0002:00000588 e:\Program\Crash\Debug\Crash.exe 32 | 00F335B8 003CFC70 0002:000025B8 e:\Program\Crash\Debug\Crash.exe 33 | 00F333FF 003CFC78 0002:000023FF e:\Program\Crash\Debug\Crash.exe 34 | 769A343D 003CFC84 0001:0000343D C:\windows\syswow64\kernel32.dll 35 | 770F9832 003CFCC4 0001:00029832 C:\windows\SysWOW64\ntdll.dll 36 | 770F9805 003CFCDC 0001:00029805 C:\windows\SysWOW64\ntdll.dll 37 | TraceBack: 38 | 当前调用函数 : 00f31560+wmain(FILE[e:\program\crash\crash\main.cpp]LINE[7]) 39 | 当前调用函数 : 00f33410+__tmainCRTStartup(FILE[f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c]LINE[583]) 40 | 当前调用函数 : 00f333f0+wmainCRTStartup(FILE[f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c]LINE[403]) 41 | 当前调用函数 : 769a342b+BaseThreadInitThunk(FILE[f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c]LINE[403]) 42 | 当前调用函数 : 770f97cf+RtlInitializeExceptionChain(FILE[f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c]LINE[403]) 43 | 当前调用函数 : 770f97cf+RtlInitializeExceptionChain(FILE[f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c]LINE[403]) 44 | ``` 45 | 46 | 最后TraceBack部分记录的是崩溃时程序执行的位置,它能够精确定位到出错位置所在源文件的行数 47 | 48 | 程序的基础是由一个老外写的MSJExceptionHandler,原文我找不到了,这里只列举出我真实参考到的文章 49 | 50 | 参考资料: 51 | 52 | [记录程序崩溃时的调用堆栈](https://blog.csdn.net/qing666888/article/details/41026375) 53 | 54 | [windows平台调用函数堆栈的追踪方法](https://blog.csdn.net/lanuage/article/details/52203447) 55 | 56 | ## V1.0 版本 57 | 在上述基础之上增添了一些功能,改写了全部的代码结构 58 | 59 | 1. 程序主要分为2个类,CStackWalker 类主要负责获取模块和堆栈信息,CBaseException 主要处理异常的相关操作 60 | 2. CBaseException 中所有方法都可以重写,其中最重要的是重写OutputString, 特别是您希望将它写到文件中的时候,只需要重写该方法,将输出写入到文件中即可 61 | 3. CBaseException 类提供两种使用方法,可以使用SET_DEFULTER_HANDLER 宏来定义全局的异常处理函数或者使用SET_DEFAUL_EXCEPTION将异常转化为C++异常,具体的使用方法参考main.cpp文件 62 | 4. 修改之前版本中由于未加载全部符号表可能导致的获取函数调用堆栈失败的情况 63 | --------------------------------------------------------------------------------