- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
当发生未处理的异常时,我想打印堆栈跟踪而不是仅仅终止。我尝试使用 SetUnhandledExceptionFilter
来做到这一点:
SetUnhandledExceptionFilter(UnhandledException);
...
LONG WINAPI UnhandledException(LPEXCEPTION_POINTERS exceptionInfo)
{
printf("An exception occurred which wasn't handled!\nCode: 0x%08X\nAddress: 0x%08X",
exceptionInfo->ExceptionRecord->ExceptionCode,
exceptionInfo->ExceptionRecord->ExceptionAddress);
return EXCEPTION_EXECUTE_HANDLER;
}
我发现这段代码工作正常。但是没有附加信息,因为 ExceptionCode
和 ExceptionAddress
无论如何都打印在系统“事件查看器”中。是否可以打印完整的堆栈跟踪,以便我可以确定发生异常的确切位置?
我找到了这段代码 https://code.google.com/p/m0d-s0beit-sa/source/browse/src/main.cpp?r=9ceb4fec21d647b169c72851d7882bef2b9c5a8a它部分解决了我的问题。仅打印发生异常的方法。但是不打印异常类型和行号。
最佳答案
这是我几年前为 Windows 编写的一些堆栈遍历代码。这是它产生的输出类型:
Walking stack.
0 DebugBreak
1 ThreadFunc2 e:\c\source\stackwalk2a.cpp(72)
2 ThreadFunc1 e:\c\source\stackwalk2a.cpp(79)
3 TargetThread e:\c\source\stackwalk2a.cpp(86)
4 BaseThreadInitThunk
5 RtlUserThreadStart
End of stack walk.
缺少的主要内容是有关异常类型的任何内容。如果您谈论的是 native 结构化/向量化异常,我很确定它也应该是可检索的。检索 C++ 异常类型可能有点困难(但我不太确定——这可能很容易)。
#include <windows.h>
#include <winnt.h>
#include <string>
#include <vector>
#include <Psapi.h>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <stdexcept>
#include <iterator>
#pragma comment(lib, "psapi.lib")
#pragma comment(lib, "dbghelp.lib")
// Some versions of imagehlp.dll lack the proper packing directives themselves
// so we need to do it.
#pragma pack( push, before_imagehlp, 8 )
#include <imagehlp.h>
#pragma pack( pop, before_imagehlp )
struct module_data {
std::string image_name;
std::string module_name;
void *base_address;
DWORD load_size;
};
typedef std::vector<module_data> ModuleList;
HANDLE thread_ready;
bool show_stack(std::ostream &, HANDLE hThread, CONTEXT& c);
DWORD __stdcall TargetThread( void *arg );
void ThreadFunc1();
void ThreadFunc2();
DWORD Filter( EXCEPTION_POINTERS *ep );
void *load_modules_symbols( HANDLE hProcess, DWORD pid );
int main( void ) {
DWORD thread_id;
thread_ready = CreateEvent( NULL, false, false, NULL );
HANDLE thread = CreateThread( NULL, 0, TargetThread, NULL, 0, &thread_id );
WaitForSingleObject( thread_ready, INFINITE );
CloseHandle(thread_ready);
return 0;
}
// if you use C++ exception handling: install a translator function
// with set_se_translator(). In the context of that function (but *not*
// afterwards), you can either do your stack dump, or save the CONTEXT
// record as a local copy. Note that you must do the stack dump at the
// earliest opportunity, to avoid the interesting stack-frames being gone
// by the time you do the dump.
DWORD Filter(EXCEPTION_POINTERS *ep) {
HANDLE thread;
DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
GetCurrentProcess(), &thread, 0, false, DUPLICATE_SAME_ACCESS);
std::cout << "Walking stack.";
show_stack(std::cout, thread, *(ep->ContextRecord));
std::cout << "\nEnd of stack walk.\n";
CloseHandle(thread);
return EXCEPTION_EXECUTE_HANDLER;
}
void ThreadFunc2() {
__try { DebugBreak(); }
__except (Filter(GetExceptionInformation())) { }
SetEvent(thread_ready);
}
void ThreadFunc1(void (*f)()) {
f();
}
// We'll do a few levels of calls from our thread function so
// there's something on the stack to walk...
//
DWORD __stdcall TargetThread(void *) {
ThreadFunc1(ThreadFunc2);
return 0;
}
class SymHandler {
HANDLE p;
public:
SymHandler(HANDLE process, char const *path=NULL, bool intrude = false) : p(process) {
if (!SymInitialize(p, path, intrude))
throw(std::logic_error("Unable to initialize symbol handler"));
}
~SymHandler() { SymCleanup(p); }
};
#ifdef _M_X64
STACKFRAME64 init_stack_frame(CONTEXT c) {
STACKFRAME64 s;
s.AddrPC.Offset = c.Rip;
s.AddrPC.Mode = AddrModeFlat;
s.AddrStack.Offset = c.Rsp;
s.AddrStack.Mode = AddrModeFlat;
s.AddrFrame.Offset = c.Rbp;
s.AddrFrame.Mode = AddrModeFlat;
return s;
}
#else
STACKFRAME64 init_stack_frame(CONTEXT c) {
STACKFRAME64 s;
s.AddrPC.Offset = c.Eip;
s.AddrPC.Mode = AddrModeFlat;
s.AddrStack.Offset = c.Esp;
s.AddrStack.Mode = AddrModeFlat;
s.AddrFrame.Offset = c.Ebp;
s.AddrFrame.Mode = AddrModeFlat;
return s;
}
#endif
void sym_options(DWORD add, DWORD remove=0) {
DWORD symOptions = SymGetOptions();
symOptions |= add;
symOptions &= ~remove;
SymSetOptions(symOptions);
}
class symbol {
typedef IMAGEHLP_SYMBOL64 sym_type;
sym_type *sym;
static const int max_name_len = 1024;
public:
symbol(HANDLE process, DWORD64 address) : sym((sym_type *)::operator new(sizeof(*sym) + max_name_len)) {
memset(sym, '\0', sizeof(*sym) + max_name_len);
sym->SizeOfStruct = sizeof(*sym);
sym->MaxNameLength = max_name_len;
DWORD64 displacement;
if (!SymGetSymFromAddr64(process, address, &displacement, sym))
throw(std::logic_error("Bad symbol"));
}
std::string name() { return std::string(sym->Name); }
std::string undecorated_name() {
std::vector<char> und_name(max_name_len);
UnDecorateSymbolName(sym->Name, &und_name[0], max_name_len, UNDNAME_COMPLETE);
return std::string(&und_name[0], strlen(&und_name[0]));
}
};
bool show_stack(std::ostream &os, HANDLE hThread, CONTEXT& c) {
HANDLE process = GetCurrentProcess();
int frame_number=0;
DWORD offset_from_symbol=0;
IMAGEHLP_LINE64 line = {0};
SymHandler handler(process);
sym_options(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
void *base = load_modules_symbols(process, GetCurrentProcessId());
STACKFRAME64 s = init_stack_frame(c);
line.SizeOfStruct = sizeof line;
IMAGE_NT_HEADERS *h = ImageNtHeader(base);
DWORD image_type = h->FileHeader.Machine;
do {
if (!StackWalk64(image_type, process, hThread, &s, &c, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
return false;
os << std::setw(3) << "\n" << frame_number << "\t";
if ( s.AddrPC.Offset != 0 ) {
std::cout << symbol(process, s.AddrPC.Offset).undecorated_name();
if (SymGetLineFromAddr64( process, s.AddrPC.Offset, &offset_from_symbol, &line ) )
os << "\t" << line.FileName << "(" << line.LineNumber << ")";
}
else
os << "(No Symbols: PC == 0)";
++frame_number;
} while (s.AddrReturn.Offset != 0);
return true;
}
class get_mod_info {
HANDLE process;
static const int buffer_length = 4096;
public:
get_mod_info(HANDLE h) : process(h) {}
module_data operator()(HMODULE module) {
module_data ret;
char temp[buffer_length];
MODULEINFO mi;
GetModuleInformation(process, module, &mi, sizeof(mi));
ret.base_address = mi.lpBaseOfDll;
ret.load_size = mi.SizeOfImage;
GetModuleFileNameEx(process, module, temp, sizeof(temp));
ret.image_name = temp;
GetModuleBaseName(process, module, temp, sizeof(temp));
ret.module_name = temp;
std::vector<char> img(ret.image_name.begin(), ret.image_name.end());
std::vector<char> mod(ret.module_name.begin(), ret.module_name.end());
SymLoadModule64(process, 0, &img[0], &mod[0], (DWORD64)ret.base_address, ret.load_size);
return ret;
}
};
void *load_modules_symbols(HANDLE process, DWORD pid) {
ModuleList modules;
DWORD cbNeeded;
std::vector<HMODULE> module_handles(1);
EnumProcessModules(process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cbNeeded);
module_handles.resize(cbNeeded/sizeof(HMODULE));
EnumProcessModules(process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cbNeeded);
std::transform(module_handles.begin(), module_handles.end(), std::back_inserter(modules), get_mod_info(process));
return modules[0].base_address;
}
关于c++ - 在 SetUnhandledExceptionFilter 的处理程序中如何打印堆栈跟踪?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15372962/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!