该通过指针来捕获。使用指针捕获异常需要你删除对象。因为它们通常从堆中分配,当你处理完异常之后, 需要调用 Delete 成员函数来删除。你不可以使用省略捕获处理器捕获 MFC 异常,这会导致一个内存泄露。必须使用 Delete 成 员函数删除 MFC 异常,而不用 delete,因为一些 MFC 异常为静态对象创建。 在释放栈的过程中抛出异常会导致进程的终止。释放栈涉及到调用析构函数,异常可以阻止调用 delete 操作符,这样会有 资源泄漏,因此异常最好不要从析构函数中抛出。如果非要在析构函数里抛出异常,必须妥善处理,避免资源泄漏。 6、异常与防御性编程 在异常发生时继续执行程序,远比执行一个正常的关闭动作要重要。如果可能,应该将精力集中在继续执行程序,并在必 须的情况下才正常地关闭程序。 可能最根本的正常关闭是一个在崩溃时可以重新启动自己的进程, 这是 Windows 资源管理器使 用的一种技术。 如果一个与错误相关的 C++异常是可预料的,如果它发生在非关键性的代码中,如果它不是发生在程序启动或结束过程中 或一个不可恢复的结构异常的结果中,这个程序就可以从其中恢复。 一旦你的程序可以从与错误相关的异常中恢复,应该先检查程序的状态和它的
文档。如果程序和
文档已经被破坏了,进程
也应该终止运行。否则,程序需要通知客户机确定动作的过程。如果客户机同意执行下去,程序应该恢复错误并继续执行。 四、返回值 并不是在所以场合下都能使用异常, 如在使用 Windows API 编程或带有 COM 编程时并不使用异常。 在异常不适合的时候, 使用返回值是一个好的办法。 返回值的基本特性: .返回值可以指示正常和不正常的函数运行,但不能阻止线程的继续运行。 .返回值很容易被忽略。 .返回值在典型情况下是一个整数,通常映射符合于一个预定义的值。 .返回值能高效地传递和接收。 因此,返回值最适合用于以下的情形:
.用于非错误的状态信息 .用于大多数情况下可以随意忽略而不会出问题的错误。 .用于更易于出现在循环中的错误。 .用于中间语言模块如 COM 组件中的错误。 VC/MFC 调试技术(下) 使用 Visual C++调试器调试 一、调试版本与发布版本 有时程序能在调试版本运行但不能运行于发布版本,反之也有可能。一般说来,一个发布版本意味着某些类型的优化,而 一个调试版本则没有优化。下面我们来看看它们的区别: 1、特别针对调试版本的编译选项 (1)/MDd,/MLd 或者/MTd 调试版本的运行时刻库有调试符号,使用了调试堆,调试堆的目的是发现内存破坏和内存泄漏,并且向用户
报告源代码的 哪个地方出了问题。特性: .调试版本的运行时刻库对内存的分配作了跟踪,允许用户检查内存泄漏。 .在刚分配的内存里写上 0xCD 的字节模式,用 0xCD 来填充刚分配的内存,有助于发现数据未被初始化的错误。 .在被释放的内存写上 0xDD 的字节模式,有助于发现已被释放的内存。 .在缓冲区的两边分配了四字节的保护数据,并用 0xFD 的字节模式作初始化,来检查写内存的上溢出和下溢出。 .在每个内存分配的地方对源代码文件名和行号作了记录,有助于用户在
源代码中对内存分配进行定位。 (2)/Od 这个选项用来关闭优化开关。因为未被优化的代码直接对应于源代码,所以比优化后的代码更容易读懂。未被优化的代码 编译和链接会更快,会有更短的调试周期。而由于优化,发布版本不见得会比调试版本运行得好,优化代码要求编译器做一些 假设, 去除冗余, 但有时这个假设是错误的, 并且去掉的冗余也有可能隐藏错误。 如发布版本的帧指针 (EBP 寄存器) (FPO) 省略 隐藏了函数原型不匹配的错误;在同步异常模式(只能由 throw 语句抛出,编译器默认,由/GX 编译