numist / Debugger

A collection of debug functions and macros intended for use in projects using the Obj-C runtime.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Debugger

Originally written for TagLib, the Debugger module provides debugging macros and functions useful to any project using the Obj-C runtime.

Wherever possible, arguments to macros are evaluated only once. If you find this is not the case, please file a ticket.

Installation

debugger.h is written to be included in your project's precompiled header, or any other place it is wanted. If using in a precompiled header, it must be bracketed inside an #ifdef __OBJC__ conditional, like so:

#ifdef __OBJC__
    // …
    #include "debugger.h"
#endif

Unfortunately, the same #ifdef __OBJC__ macro already present in debugger.h doesn't have the same effect in Xcode (tested in 4.5+) (why?).

debugger.c will need to be built and linked as appropriate.

Usage

Debugger provides the following utilities:

--- ### `bool AmIBeingDebugged()` Returns whether a debugger is attached.

Used by DebugBreak to determine if it's safe to interrupt execution. If DEBUG is not defined, this is never called internally, but is still available.

--- ### `DebugBreak()` Breaks into the debugger, if attached.

If there is no debugger attached, does nothing. If DEBUG is not defined, does nothing.

--- ### `Check(exp)` [`Log`](#__github__readme_md__Log)s an error message and invokes `DebugBreak` if condition `exp` evaluates to `false`.

If DEBUG is not defined, does nothing.

--- ### `NotTested()` [`Log`](#__github__readme_md__Log)s a "NOT TESTED" message and invokes `DebugBreak`.

If DEBUG is not defined, does nothing.

--- ### `Log(…)` Emits a message via [`NSLog`](https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/miscellaneous/foundation_functions/reference/reference.html#//apple_ref/c/func/NSLog).

Prepends the file path, line number, and current function to the format string. Parameters are passed directly to NSString +stringWithFormat:. If DEBUG is not defined, does nothing.

Log can be overridden by defining it before including debugger.h, for example if you wanted to add a component prefix to messages in a file:

#define Log(fmt, ...) NSLog(@"MyComponent: %@", [NSString stringWithFormat:(fmt), ##__VA_ARGS__])

Messages sent to user-defined Log includes only a simple message, omitting any file, line, or method information that may be available.

Example
Log(@"View hierarchy: %@", [[UIWindow keyWindow] recursiveDescription]);
--- ### `Assert(exp)` [`Log`](#__github__readme_md__Log)s an error message, invokes `DebugBreak`, and then `abort`s.

If DEBUG is not defined, does nothing.

Example
Assert(NO); // ifdef DEBUG, kaboom.
--- ### `NotReached()` [`Log`](#__github__readme_md__Log)s a "NOT REACHED" message, invokes `DebugBreak`, and then `abort`s.

If DEBUG is not defined, does nothing.

--- ### `BailUnless(exp,return_value)` [`Check`](#__github__readme_md__Check)s the expression, and then returns `return_value` if the check failed.

If DEBUG is not defined, this macro still bails, but does not break into the debugger or log any messages.

Example
- (NSArray *)foo {
    BailUnless(NO, (NSArray *)nil);
    NotReached();
}

When using BailUnless with a function or method returning void:

- (void)foo {
    BailUnless(NO,);
    NotReached();
}
--- ### `BailWithBlockUnless(exp,block)` [`Check`](#__github__readme_md__Check)s the expression, and then returns the result returned by `block()` if the check failed.

If DEBUG is not defined, this macro still bails, but does not break into the debugger or log any messages.

Example
- (NSArray *)foo {
    BailWithBlockUnless(NO, ^{
        // Clean up…
        return (NSArray *)nil;
    });
    NotReached();
}

When using BailWithBlockUnless with a function or method returning void:

- (void)foo {
    BailWithBlockUnless(NO, ^{
        // Clean up…
    });
    NotReached();
}
--- ### `BailWithGotoUnless(exp,label)` [`Check`](#__github__readme_md__Check)s the expression, and then jumps to `label` if the check failed.

If DEBUG is not defined, this macro still bails, but does not break into the debugger or log any messages.

Example
- (NSArray *)foo {
    BailWithGotoUnless(NO, error);
    NotReached();
error:
  // Clean up…
  return nil;
}

License/Credits

The most interesting code in this project is not originally mine, but was assembled, tested, and in some cases rewritten by me from public sources (Stack Overflow, public documentation, freely released snippets). Thus all code in this project is released to the public domain. While more complete attribution is provided in the source, credit is especially due for:

  • bool AmIBeingDebugged() provided by an Apple TechNote.
  • DebugBreak() for iOS code built with toolchains that do not support __builtin_debugtrap provided by m20.nl (now defunct)
  • DebugBreak() for OS X code built with toolchains that do not support __builtin_debugtrap provided by Matt Gallagher

About

A collection of debug functions and macros intended for use in projects using the Obj-C runtime.


Languages

Language:C 100.0%