gpt4 book ai didi

Windows 访问冲突的 C++ 调用堆栈

转载 作者:行者123 更新时间:2023-11-30 05:40:26 24 4
gpt4 key购买 nike

我一直在尝试让 Windows 应用程序在发生崩溃(错误的内存访问或被零除)或标准 c++ 异常时转储调用堆栈。

我已经构建了 StackWalker 并将其链接到我的应用程序中,并使用 /EHa 编译了我的应用程序.

#include "win/StackWalker.h"

extern int runapp(int argc, char **argv);

// The exception filter function:
LONG WINAPI ExpFilter(EXCEPTION_POINTERS* pExp, DWORD dwExpCode) {
StackWalker sw;
sw.ShowCallstack(GetCurrentThread(), pExp->ContextRecord);
return EXCEPTION_EXECUTE_HANDLER;
}

int main(int argc, char *argv[]) {
__try
{
return runapp(argc, argv);
}
__except (ExpFilter(GetExceptionInformation(), GetExceptionCode()))
{
}
}

真正的程序是通过 runapp() 启动的,因为不可能直接在 __try 范围内实例化需要展开(销毁)的对象。

我的问题是当我使用这段代码强制我的程序崩溃时没有捕获到任何东西:

int *data1 = 0;
*data1 = 0;

换句话说,它只是“正常”崩溃

有没有人有提示?

最佳答案

/EHa 开关告诉编译器您要处理 C++ try/catch block 内的 SEH 异常。在您的代码中,您改用 SEH 异常处理程序。这是我正在使用的一种工作方法:

dbgutils.h

#pragma once

#include <eh.h>
#include <windows.h>
#include <string>
#include <sstream>
#include <iomanip>
#include <boost/optional.hpp>

#include "StackWalker.h"

class CSO3SEHException
{
public:
CSO3SEHException(unsigned int nCode, EXCEPTION_POINTERS* pEx);
std::string what();
std::string stack();
private:
std::string m_sWhat, m_sStack;
std::string seName(const unsigned int& nCode);
boost::optional<std::string> seInfo(unsigned int nCode, EXCEPTION_POINTERS* pEx);
void seStack(EXCEPTION_POINTERS* pEx);
void seExceptionInfo(unsigned int nCode, EXCEPTION_POINTERS* pEx);
};

class CCustomStackWalker : public StackWalker
{
public:
CCustomStackWalker(std::stringstream* ss);
protected:
virtual void OnOutput(LPCSTR szText);
private:
std::stringstream* m_sOut;
};

void _so3_seh_translate(unsigned int code, _EXCEPTION_POINTERS *ep);
void ReportSEHException(CSO3SEHException& ex);

dbgutils.cpp

#include "dbgutils.h"

CCustomStackWalker::CCustomStackWalker(std::stringstream* ss)
{
m_sOut = ss;
}

void CCustomStackWalker::OnOutput(LPCSTR szText)
{
size_t sLen = strlen(szText);
std::string s = std::string(szText, sLen);

(*m_sOut) << s << std::endl;
}

CSO3SEHException::CSO3SEHException(unsigned int nCode, EXCEPTION_POINTERS* pEx)
{
seExceptionInfo(nCode, pEx);
seStack(pEx);
}

std::string CSO3SEHException::what()
{
return(m_sWhat);
}

std::string CSO3SEHException::stack()
{
return(m_sStack);
}

std::string CSO3SEHException::seName(const unsigned int& nCode)
{
switch (nCode)
{
case EXCEPTION_ACCESS_VIOLATION: return ("Access Violation");
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return ("Range Check");
case EXCEPTION_BREAKPOINT: return ("Breakpoint");
case EXCEPTION_DATATYPE_MISALIGNMENT: return ("Datatype misaligment");
case EXCEPTION_ILLEGAL_INSTRUCTION: return ("Illegal instruction");
case EXCEPTION_INT_DIVIDE_BY_ZERO: return ("Divide by zero");
case EXCEPTION_INT_OVERFLOW: return ("Integer overflow");
case EXCEPTION_PRIV_INSTRUCTION: return ("Privileged instruction");
case EXCEPTION_STACK_OVERFLOW: return ("Stack overflow");
default: return("UNKNOWN EXCEPTION");
}
}

boost::optional<std::string> CSO3SEHException::seInfo(unsigned int nCode, EXCEPTION_POINTERS* pEx)
{
std::stringstream ss;
if (EXCEPTION_ACCESS_VIOLATION == nCode)
{
ss << (pEx->ExceptionRecord->ExceptionInformation[0] ? "write " : " read");
ss << std::hex << std::setfill('0');
ss << " of address 0x" << std::setw(2*sizeof(void*)) << (unsigned)pEx->ExceptionRecord->ExceptionInformation[1];
return(ss.str());
}

return(nullptr);
}

void CSO3SEHException::seStack(EXCEPTION_POINTERS* pEx)
{
std::stringstream ss;
CCustomStackWalker sw(&ss);
sw.ShowCallstack(GetCurrentThread(), pEx->ContextRecord);
m_sStack = ss.str();
}

void CSO3SEHException::seExceptionInfo(unsigned int nCode, EXCEPTION_POINTERS* pEx)
{
std::stringstream ss;
ss << seName(nCode);
ss << std::hex << std::setfill('0');
ss << " at 0x" << std::setw(2*sizeof(void*)) << pEx->ExceptionRecord->ExceptionAddress;

auto pSInfo = seInfo(nCode, pEx);
if (pSInfo)
ss << *pSInfo;

m_sWhat = ss.str();
}

void _so3_seh_translate(unsigned int code, _EXCEPTION_POINTERS *ep)
{
throw CSO3SEHException(code, ep);
}

void ReportSEHException(CSO3SEHException& ex)
{
std::string sError = ex.what();
std::string sStack = ex.stack();
//do some error reporting here
}

代码中的某处:

//You have to call _set_se_translator in all threads
_set_se_translator(_so3_seh_translate);
try
{
//do something exception-prone
}
catch (CSO3SEHException & pSEH)
{
ReportSEHException(pSEH);
}
catch (std::exception& err)
{
//handle c++ exceptions
}

关于Windows 访问冲突的 C++ 调用堆栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31639611/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com