国家安全局这么做有什么意义呢?

我必须问这个问题,因为: 我唯一认识到的是,如果断言失败,应用程序崩溃。这就是使用 NSAssert 的原因吗?还有什么好处呢?将 NSAssert 置于我在代码中做出的任何假设之上是正确的吗,比如一个函数永远不应该接收 -1作为参数,但可以接收 -0.9或 -1.1?

71189 次浏览

断言是为了确保一个值是它应该是什么。如果断言失败,就意味着出了问题,应用程序就会退出。使用断言的一个原因是,如果传递给它的某个参数不是某个值(或某个范围的值) ,那么如果你有某个函数不会表现正常,或者会产生非常糟糕的副作用,你可以使用断言来确保该值是你所期望的值,如果不是,那么就真的出问题了,所以应用程序退出。断言对于调试/单元测试非常有用,当您提供框架来阻止用户做“邪恶”的事情时也是如此。

断言通常用于强制特定方法或逻辑片段的预期使用。假设您正在编写一个方法,该方法计算两个大于零的整数之和。为了确保该方法始终按预期使用,您可能会放置一个测试该条件的断言。

简短的回答: 它们强制您的代码只按预期使用。

NSAssert(及其与 stdlib 等效的 assert)用于在开发过程中检测编程错误。在生产(已发布)应用程序中,您永远不应该有一个失败的断言。因此,可以断言从不向需要正参数的方法传递负数。如果在测试过程中断言失败,那么就有一个 bug。但是,如果传递的值是由用户输入的,那么您需要对输入进行适当的验证,而不是依赖于生产中的断言(您可以为禁用 NSAssert*的版本构建设置 # Definition。

我实际上不能使用 NSAssert,但是我想它的工作方式与 C 语言的 asser()类似。

断言()用于在代码中强制执行语义契约。您会问,这是什么意思?

正如您所说的: 如果您有一个永远不应该接收 -1的函数,那么可以通过声明()强制执行:

void gimme_positive_ints(int i) {
assert(i > 0);
}

现在您将在错误日志(或 STDERR)中看到类似的内容:

Assertion i > 0 failed: file example.c, line 2

因此,它不仅可以安全地防范潜在的不良输入,而且还可以以一种有用的标准方式记录它们。

对了,至少在 C 语言中断言()是一个宏,所以您可以在发布代码中将断言()重新定义为 no-op。我不知道 NSAssert (或者更多的 asser())是否是这种情况,但是编译出这些检查是非常有用的。

除了上面所说的,NSAssert()的默认行为(与 C 的 assert()不同)是抛出异常,您可以捕获并处理该异常。例如,Xcode 就是这样做的。

要完全回答他的问题,任何类型的断言都是为了帮助调试。更有价值的做法是在错误源处捕获错误,然后在错误导致崩溃时在调试器中捕获它们。

例如,您可以将一个值传递给一个期望值在某个范围内的函数。该函数可以存储该值以供以后使用,并在以后使用应用程序崩溃时使用。在此场景中看到的调用堆栈不会显示错误值的来源。最好是在坏值进来的时候抓住它,找出谁在传递坏值,以及为什么传递坏值。

只是澄清一下,正如有人提到但没有完全解释的那样,拥有和使用断言而不仅仅是创建定制代码(例如,执行 if 和引发一个坏数据异常)的原因是断言应该被禁用于生产应用程序。

在开发和调试期间,将启用断言以捕获错误。当断言被计算为 false 时,程序将停止。 但是,在为生产环境编译时,编译器会省略断言代码,实际上会使您的程序运行得更快。到那时,希望你已经修复了所有的错误。 如果您的程序在生产环境中仍然存在 bug (当断言被禁用并且程序“跳过”断言时) ,那么您的程序可能会在其他时候崩溃。

来自 NSAssert 的帮助: “如果定义了预处理器宏 NS _ BLOCK _ ASSERTION,断言将被禁用。” 因此,只需将宏放在分发目标中[仅仅]。

值得指出的是,除了运行时检查之外,断言编程是通过契约设计代码时使用的一个重要工具。

更多关于主张和合同设计的信息可以在下面找到:

断言(软件开发)

合同设计

用断言编程

合约设计范例〔平装本〕

NSAssert 给你的不仅仅是应用程序崩溃。它告诉您发生断言的类、方法和行。还可以使用 NS _ BLOCK _ ASSERTION 轻松地停用所有断言。从而使其更适合于调试。另一方面,抛出 NSException只会使应用程序崩溃。它也不能说明异常的位置,也不能如此简单地禁用它。请看下面图片中的差异。

应用程序崩溃是因为一个断言也引发了一个异常,正如 NSAssert 文件所说:

调用时,断言处理程序将输出一条错误消息,该消息 包含方法和类名(或函数名) 引发一个 NSInternalInconcencyException 异常。

返回文章页面 NSAssert:

Logs after an assertion

例外:

Logs after an exception

NSAssert使应用程序在符合条件时崩溃。如果与条件不匹配,将执行下一个语句。寻找下面的前任:

我只是创建了一个应用程序来测试什么是 NSAssert的任务是:

    - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self testingFunction:2];
}


-(void)testingFunction: (int)anNum{
// if anNum < 2 -> the app will crash
// and the NSLog statement will not execute
// that mean you cannot see the string: "This statement will execute when anNum < 2"
// into the log console window of Xcode
NSAssert(anNum >= 2, @"number you enter less than 2");
// If anNum >= 2 -> the app will not crash and the below
// statement will execute
NSLog(@"This statement will execute when anNum < 2");
}

在我的代码中,这个应用程序不会崩溃,测试用例是:

  • 应用程序不会崩溃,您可以看到输出日志控制台窗口中的日志字符串: “此语句将在 anNum < 2时执行”
  • anNum < 2-> 应用程序将崩溃,您将看不到日志字符串: “此语句将在 anNum < 2时执行”