Objective c 目标C-如何以编程方式停止调试执行,同时允许继续?
在目标C中使用标准NSAssert(condition_which_evaluate_true,@“error message”)语句,并在断点导航器中添加一个“All Exceptions”断点,成功地使调试生成在以编程方式指定条件时停止执行 很好,但大多数时候,当我调试时,我也想在这一点之后继续正常的程序执行。通常,在断言失败后继续执行程序有助于追踪混淆/错误的来源。至少在我记忆中,当我在另一个平台上编程时Objective c 目标C-如何以编程方式停止调试执行,同时允许继续?,objective-c,breakpoints,assertions,continuation,Objective C,Breakpoints,Assertions,Continuation,在目标C中使用标准NSAssert(condition_which_evaluate_true,@“error message”)语句,并在断点导航器中添加一个“All Exceptions”断点,成功地使调试生成在以编程方式指定条件时停止执行 很好,但大多数时候,当我调试时,我也想在这一点之后继续正常的程序执行。通常,在断言失败后继续执行程序有助于追踪混淆/错误的来源。至少在我记忆中,当我在另一个平台上编程时 在Objective C开发中有这样做的标准方法吗?听起来您想使用条件断点。如果通过
在Objective C开发中有这样做的标准方法吗?听起来您想使用条件断点。如果通过在源代码的空白处单击来设置断点,然后按住ctrl键并单击蓝色的小断点,则可以编辑一些选项,包括使断点以变量的值为条件 这里有一个和更多的信息 也有一些很好的建议
如果坚持以编程方式触发断点,请编写函数并在其中放置断点:
void MyConditionalBreak(BOOL condition, NSString *comment)
{
if (condition) {
NSLog(@"Stopped because %@", comment); // SET BREAKPOINT ON THIS LINE
}
}
然后您可以用与NSAssert类似的方式调用此函数。如果在项目的预编译头文件(Whatever.pch)中声明函数,那么它将在所有源文件中可用,而无需显式地导入任何内容。我决不是这方面的专家,但我使用的代码可以通过键盘输入进入调试器 由github上的domesticcatsoftware完成 看看它的主文件的顶部,看看它是如何做到的 它引用了一些源代码,但根据我的经验,它是最新的,需要使用当前的程序集才能进入armv6/7和模拟器上的调试器 更多背景信息的外部参考
- 有办法。这不是Objective-C的东西,而是Unix的东西
kill(getpid(), SIGSTOP);
或者简单地说:
raise(SIGSTOP);
迅速:
raise(SIGSTOP)
这将中断\uuuu kill
或\uuuuu pthread\u kill
函数中的调试器。然后,您将需要上几个堆栈帧来查看名为kill
或raise
的帧。可以使用调试器的continue命令恢复执行
请注意,如果您没有在调试器下运行并执行此操作,您的应用程序将挂起。查看[Technical Q&a QA1631:检测调试器](。您可以使用该信息编写一个包装函数或宏,在调试器下运行时只发送SIGSTOP
。可能会有所帮助
此外,基础框架提供了一个不同的断言宏,用于常规函数。它是<代码> NSCAssert < /C> > < /P> < P>使用Rob的评论,以及“IOS5编程:推限”的一些想法。,以及Lumberjack框架,这里有一个宏,可以让调试器在
调试
构建中的断言期间停止并允许继续,但在发布
(或者实际上是任何非-DEBUG
)构建过程中,它总是这样做
这些宏需要函数amibeingdebuged()
,您可以从苹果的链接Rob获得该函数:Technical Q&A QA1631:Detecting the Debugger(您还需要在构建设置中定义DEBUG
)
请注意,在非
DEBUG
版本中,我选择了Lumberjack的DDLogError()
而不是NSLog()
,因为它会吐出致命断言发生的方法、文件和行号。如果您想使用控制台,一个简单的技巧是:
if (!condition_which_should_evaluate_true) {
; // Put breakpoint here
}
然后将断点放在该行内。如果条件的计算结果为“否”,则会调用断点。我是这样做的:
首先,在“断点”选项卡中,如果引发任何异常,我将我的应用程序设置为中断:
然后在代码中(我通常有公共头文件,其中包含像这样的公共定义,我在任何地方都导入这些定义):
现在,您可以像NSAssert一样使用它,但您只需触发一个断点,而不是终止您的应用程序:
MYAssert(bEverythingOkay, @"Something went wrong!");
// Or with arguments of course
MYAssert(bEverythingOkay, @"Something went wrong (TestValue=%zd; Reason=%@)", myTestValue, [this getLastError]);
不知道为什么没有其他人给出一个明确直截了当的答案…已经五年了,但迟做总比不做强
预处理器: 用法: 要使用它,只需键入以下内容:
manualBreakpoint();
笔记:
这将在调用该代码时停止应用程序,并在堆栈跟踪中显示当前方法(以及记录应用程序停止时的文件名和行号),如果您处于调试模式,如果您处于appstore的生产模式(也称为发布、分发或存档),则它将不执行任何操作
毫无疑问,条件断点有助于调试,但正如我在标题中所说,我想以编程方式(即在代码中)停止执行,原因有三:(1)在编码过程中指定断点是一件痛苦的事情(切换到鼠标、右键单击、在文本字段中单击等;或者执行一长串模糊的键盘快捷键);(2)我使用断言的方式意味着我通常希望它们与断点分开组织,而据我所知,断点窗口是无法完成的;以及(3)最重要的是,断点不能像断言那样在项目之间进行移植。@Merk我添加了一个替代方法,即只需编写自己的函数并在其中放置断点,一次就完成了。我认为这比信号/陷阱解决方案要容易一些,后者将要求您处理堆栈帧。如果您想继续执行,只需将错误打印到屏幕上。为什么不使用assert宏来调用始终设置断点的例程?@Hot-Licks:必须爬升堆栈才能找到调用的位置、访问内存等,这很烦人。下面的
kill
方法没有那么麻烦。调试器显示堆栈--
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__]); }
MYAssert(bEverythingOkay, @"Something went wrong!");
// Or with arguments of course
MYAssert(bEverythingOkay, @"Something went wrong (TestValue=%zd; Reason=%@)", myTestValue, [this getLastError]);
#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