Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 目标C-如何以编程方式停止调试执行,同时允许继续?_Objective C_Breakpoints_Assertions_Continuation - Fatal编程技术网

Objective c 目标C-如何以编程方式停止调试执行,同时允许继续?

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开发中有这样做的标准方法吗?听起来您想使用条件断点。如果通过

在目标C中使用标准NSAssert(condition_which_evaluate_true,@“error message”)语句,并在断点导航器中添加一个“All Exceptions”断点,成功地使调试生成在以编程方式指定条件时停止执行

很好,但大多数时候,当我调试时,我也想在这一点之后继续正常的程序执行。通常,在断言失败后继续执行程序有助于追踪混淆/错误的来源。至少在我记忆中,当我在另一个平台上编程时


在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