objective-c 什么是“中止陷阱”以及如何调试它?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/431235/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:02:02  来源:igfitidea点击:

What is an "Abort trap" & how do I debug it?

objective-cdebugging

提问by mamcx

I'm getting this message each time I compile my project:

每次编译我的项目时都会收到此消息:

RunIPhoneUnitTest.sh: line 92: 31389 Abort trap              "$TARGET_BUILD_DIR/$EXECUTABLE_PATH" -RegisterForSystemEvents

I understand is a problem in my code, but then I don't figure how solve or found it.

我知道我的代码有问题,但后来我不知道如何解决或找到它。

The strange thing, is that I get this with this call:

奇怪的是,我通过这个电话得到了这个:

-- This is the interface
@interface DbObject : NSObject {
    NSInteger Id;
    NSDate* timeStamp;
}

@property (nonatomic) NSInteger Id;
@property (nonatomic, retain) NSDate *timeStamp;
----
This fail with above error
----
NSString * filter = [NSString stringWithFormat:"id = %@", ds.Id, nil];

BUT the wird thing is that I delete that line, that method and still get it! Is making my crazy.

但奇怪的是,我删除了那行,那个方法,仍然得到它!正在让我发疯。

Currently, I'm thinking in delete code until not get a error & start adding it, but wonder if exist a more pragmatic solution...

目前,我正在考虑删除代码,直到没有出现错误并开始添加它,但想知道是否存在更实用的解决方案......

回答by Jason Coco

An abort trap usually means that abort was called somewhere. This is most likely happening because your unit test harness code is throwing an exception that it's not expecting and simply handling this by calling abort(3). The abort call is not very easy to debug because it provides no information regarding who called it or why, never returns and generates a SIGABRT. You could install a new handler for SIGABRT and place a breakpoint there and then at least examine the current call stack... but read the rest for information on why this is happening in the first place.

中止陷阱通常意味着中止在某处被调用。这很可能发生,因为您的单元测试工具代码抛出了一个意外异常,只需通过调用 abort(3) 来处理它。中止调用不是很容易调试,因为它不提供有关谁调用它或为什么调用它的信息,从不返回并生成 SIGABRT。您可以为 SIGABRT 安装一个新的处理程序并在那里放置一个断点,然后至少检查当前的调用堆栈……但首先阅读其余部分以了解为什么会发生这种情况。

However, the problem with your code above is that NSInteger is not an object type, it's a regular primitive. To correct your error, replace the failing line with this:

但是,上面代码的问题在于 NSInteger 不是对象类型,它是常规原语。要纠正您的错误,请将失败的行替换为:

NSString *filter = [NSString stringWithFormat:@"id = %lld", (long long)ds.Id];

First, stringWithFormattakes an NSStringobject as a parameter, so you need to use the '@' character to specify that the string literal is an NSString. This is very important since @"blah blah"is actually translated into an object. The call you're making to stringWithFormatis expecting the NSString object information to be resident at that memory address, but instead it's getting a string of characters and is most likely exploding there. Make sure that all your string literals are @"blah blah"where an NSString type is expected and that they're not simple c-strings.

首先,stringWithFormat将一个NSString对象作为参数,因此需要使用“@”字符来指定字符串字面量是一个 NSString。这非常重要,因为@"blah blah"它实际上被翻译成一个对象。您正在进行的调用stringWithFormat期望 NSString 对象信息驻留在该内存地址处,但它得到的是一串字符,并且很可能在那里爆炸。确保所有字符串文字都@"blah blah"在预期 NSString 类型的位置,并且它们不是简单的 c 字符串。

Second, the '@' character in the format string specifies an object. Since NSInteger is not an object, you can't use this format character. Instead use %lld to specify a long long integer. Finally, you don't need to add the nilat the end of the parameter list when using stringWithFormatsince the format string itself specifies how many parameters to expect.

其次,格式字符串中的“@”字符指定了一个对象。由于 NSInteger 不是对象,因此您不能使用此格式字符。而是使用 %lld 来指定 long long 整数。最后,使用时不需要nil在参数列表的末尾添加 ,stringWithFormat因为格式字符串本身指定了期望的参数数量。

As an aside, the reason that %lldis used instead of just %dis that NSInteger changes size depending on whether you're compiling for a 32-bit or 64-bit target. By promoting the NSInteger to the long longtype and using the %lldspecifier you make sure that you won't have truncation issues in the future if you compile for 64-bit and your NSInteger value requires more than 32 bits to store.

顺便说一句,%lld使用而不是仅仅使用%dNSInteger的原因是根据您是为 32 位还是 64 位目标编译而改变大小。通过将 NSInteger 提升为long long类型并使用说明%lld符,如果您为 64 位编译并且您的 NSInteger 值需要超过 32 位来存储,您可以确保将来不会出现截断问题。