Exception handling is an important language feature for building more robust software programs. It is primarily concerned with capturing abnormal events, with the help of catch handlers for supporting recovery actions. In this paper, we advocate for a specification logic that can uniformly handle exceptions, program errors and other kinds of control flows. Our logic treats exceptions as possible outcomes that could be later remedied, while errors are conditions that should be avoided by user programs. This distinction is supported through a uniform mechanism that captures static control flows (such as normal execution) and dynamic control flows (such as exceptions) within a single formalism. Following Stroustrup's definition [15, 9], our verification technique could ensure exception safety in terms of four guarantees of increasing quality, namely no-leak guarantee, basic guarantee, strong guarantee and no-throw guarantee.