Goal C - How to programmatically stop execution for debugging, allowing continuation?

I was successful in having my debug builds stop running when the condition was programmed by the software using the standard NSAssert instruction (condition_which_should_evaluate_true, @ "error message in Objective-C and adding a breakpoint navigator to the breakpoint" All Exceptions ".

Well and good, but most of the time when I am debugging, I would also like to continue the normal execution of the program after this point. Often, continuing a program after an unsuccessful statement helps keep track of the source of confusion / error. At least, as far as I remember, when I was programming on another platform.

Is there a standard way to do this in developing Objective-C?

+7
source share
7 answers

There is a way. This is not an Objective-C thing, it is a Unix thing.

kill(getpid(), SIGSTOP); 

or simply:

 raise(SIGSTOP); 

This will break off in the debugger in the __kill function. You will need to go up to the frame of a stack or two to look at a frame called kill . You can use the continue command of the debugger to resume execution.

Please note that if you are not running under the debugger and are doing this, your application will simply freeze. Take a look at Technical Q & A QA1631: Debugger Detection . You can use this information to write a wrapper function or a macro that sends SIGSTOP when working in the debugger.

In addition, the Foundation Framework provides another assert macro for use in regular functions. This is NSCAssert .

+12
source

It looks like you want to use conditional breakpoints. If you set a breakpoint by clicking on the edge of the source code, press Ctrl-click on the small blue breakpoint, you can edit some parameters, including making the breakpoint conditional on the value of the variable.

Here 's a blog post with some screenshots and more details.

This stack overflow question contains some good pointers.


If you insist on starting the breakpoint programmatically, then write a function and place a breakpoint in it:

 void MyConditionalBreak(BOOL condition, NSString *comment) { if (condition) { NSLog(@"Stopped because %@", comment); // SET BREAKPOINT ON THIS LINE } } 

You can then call this function in the same way as NSAssert. If you declare a function in your precompiled header file (Whatever.pch), it will be available in all of your source files, without explicit #import anything.

+2
source

Here is how I do it:

First, on the Breakpoints tab, I set that my applications break if an exception occurs: All exceptions

Then in the code (I usually have a common header file containing common definitions like this one that I import everywhere):

 static void ThrowException(NSString* reason) { @try { @throw [NSException exceptionWithName:@"DebugAssertionException" reason:reason userInfo:nil]; } @catch (NSException * e) { NSLog(@"%@", e); } } #define MYAssert(test, fmt, ...) if (!(test)) { ThrowException([NSString stringWithFormat:@"%s !!! ASSERT !!! " fmt, __PRETTY_FUNCTION__, ##__VA_ARGS__]); } 

Now you can use it as an NSAssert, but instead of killing your application, you simply call a breakpoint:

 MYAssert(bEverythingOkay, @"Something went wrong!"); // Or with arguments of course MYAssert(bEverythingOkay, @"Something went wrong (TestValue=%zd; Reason=%@)", myTestValue, [this getLastError]); 
+2
source

I am by no means an expert in this field, but I use code that can enter the debugger from the keyboard.

DCIntrospect for github home software does this.

Take a look at the top of the main DCIntrospect.m file and see how it does it.

It refers to several sources, but in my experience it is completely updated with the current build, which is necessary for hacking into the debugger on armv6 / 7 and the simulator

External links for more information

+1
source

Not sure why no one else gave a clear direct answer ... It was five years old, but better late than never.


Preprocessor:

 #ifdef DEBUG #define manualBreakpoint() \ NSLog(@"\n\n\ Breakpoint called on: \n\n\ File: %s \n\n\ Line number: %i", __FILE__, __LINE__);\ \ raise(SIGSTOP) #else #define manualBreakpoint() ; #endif 

Using:

To use it, simply enter the following: manualBreakpoint();

Notes:

This will cause the application to stop when you call this code and display the current method in your stack trace (as well as register the file name and number of the number that your application stopped at). IFF you are in debug mode if you are in production mode for the appstore (aka release, distribution or archive) will do nothing.

+1
source

Using Rob's comments and some ideas from โ€œios5 Programming: Pushing the Limitsโ€ and the Lumberjack framework, here is a macro to make the debugger stop and allow continuation during the approval in DEBUG build, but otherwise do as it always happens during RELEASE (or nothing at all -DEBUG ).

 #ifdef DEBUG #define MyAssert(condition, desc, ...) \ if (!(condition)) { \ NSLog((desc), ## __VA_ARGS__); \ if (AmIBeingDebugged()) \ kill (getpid(), SIGSTOP); \ else { \ NSLog(@"%@, %d: could not break into debugger.", THIS_FILE, __LINE__); \ } \ } #define MyCAssert(condition, desc, ...) \ if (!(condition)) { \ NSLog((desc), ## __VA_ARGS__); \ if (AmIBeingDebugged()) \ kill (getpid(), SIGSTOP); \ else \ NSLog(@"%@, %d: could not break into debugger.", THIS_FILE, __LINE__)); \ } \ } #else //NOT in DEBUG #define MyAssert(condition, desc, ...) \ if (!(condition)) { \ DDLogError((desc), ## __VA_ARGS__); \ //use NSLog if not using Lumberjack NSAssert((condition), (desc), ## __VA_ARGS__); \ } #define MyCAssert(condition, desc, ...) \ if (!(condition)) { \ DDLogError((desc), ## __VA_ARGS__); \ //use NSLog if not using Lumberjack NSCAssert((condition), (desc), ## __VA_ARGS__); \ } #endif //end DEBUG #endif 

These macros require the AmIBeingDebugged() function, which you can get from Apple here. Rob gave: Technical Q&A QA1631: Detecting a Debugger. (You also need to define DEBUG in the build settings.)

Note that I chose Lumberjack DDLogError() over NSLog() on non- DEBUG lines, because it will spit out the method, file number, and line number where the fatal statement occurred.

0
source

A simple trick if you want to use the console is:

 if (!condition_which_should_evaluate_true) { ; // Put breakpoint here } 

Then you put your breakpoint on this line. If the condition is NO, then a breakpoint is called.

0
source

All Articles