1

我有以下问题:我有一个用 C++ 编写的应用程序(永远不会结束的服务器)作为服务运行,其中包含主线程内部还有 3 个线程(主要执行 IO)。

在主循环中,我捕获了所有可能的异常。

该进程终止,主循环或线程本身没有打印任何内容。我在事件日志中看到该进程以代码 1000 停止。

  1. Windows 是否像在 unix 中一样创建核心文件?
  2. 如果从事件日志中我得到一个内存地址,有没有办法知道它发生在应用程序的哪个部分?
  3. 也许这是一个线索:在它发生的同时,我启动了另一个应用程序(不是同一类型)。
4

5 回答 5

5

尝试将 windbg 设置为事后调试器。

  1. 安装windbg
  2. 从命令行执行“ windbg -I
  3. 启动您的应用程序,然后当您的应用程序遇到未处理的异常时,windbg 将被激活。
  4. 从 windbg 使用"kb" or "!uniqstack"查看堆栈跟踪。

    在这里查看更多命令。
    在这里查看如何分析。

并尝试使用 SEH:

#include "windows.h"
#include "stdio.h"

DWORD FilterFunction() 
{ 
 printf("you will see this message first.\n");
 return EXCEPTION_EXECUTE_HANDLER; 
} 


int main(char** argv, int c)
{
 __try
 {
  int this_will_be_zero = (c == 9999);
  int blowup = 1 / this_will_be_zero;
 }
 __except ( FilterFunction()) 
 {
  printf("you will see this message\n");
 }

 return 0;
}
于 2010-01-06T12:52:30.310 回答
2

在构建应用程序时需要使用 /EHa 编译器开关,以便使用 C++ try/catch 构造捕获 Windows 结构化异常(例如访问冲突)。

在 Visual Studio 中,这是在项目属性配置属性 -> C/C++ -> 代码生成 -> 启用 C++ 异常中。你想要“是的,有 SEH 异常 (/EHa)”。我记得阅读设置它有一些明显的缺点,尽管我不记得它们到底是什么。

链接:关于 C++ 异常处理模型的 MSDN

编辑:正如whunmr所建议的,直接使用结构化异常可能比 /EHa 更好

于 2010-01-06T12:58:53.577 回答
2

请记住catch(...),除非您使用结构化异常处理,否则不会拦截代码中可能出错的所有内容。例如

#include “stdio.h”
int main(char** argv, int c)
{
  尝试 {
    int this_will_be_zero = (c == 9999);
    int 爆破 = 1 / this_will_be_zero;
  } 抓住 (...) {
    printf("你不会看到这条信息\n");
  }
}
于 2010-01-06T11:56:24.137 回答
1

Windows 是否像在 unix 中一样创建核心文件?

它不会,自动。但是,您可以通过在代码中实现它或使用外部应用程序如 windbg 或Dr. Watson来启用此类文件

如果从事件日志中我得到一个内存地址,有没有办法知道它发生在应用程序的哪个部分?

一般来说,如果您不保留调试信息文件(pdb),则没有办法

也许这是一个线索:在它发生的同时,我启动了另一个应用程序(不是同一类型)。

这不是有用的信息,除非两个应用程序相互交互

于 2010-01-06T13:11:17.813 回答
1

Windows 将根据以下设置将您使用的任何程序用作调试器:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug]
“自动”=“0”
"调试器"="My_Debugger" -p %ld -e %ld"
"UserDebuggerHotKey"=dword:00000000

您可以更改My_Debugger为用于调试的任何程序/IDE 的完整路径。

这通常设置为 Dr Watson,它将创建一个不是您想要的崩溃日志条目。

于 2010-01-06T13:56:17.657 回答