简体   繁体   English

为什么发布版本会失败而不进行调试?

[英]Why does release build fail and not debug?

I have a device/debug build that works fine. 我有一个运行良好的设备/调试版本。 When I build for release and distribute onto the device, I get this error: 当我进行发行并分发到设备上时,出现以下错误:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[UILabel setWidth:]: unrecognized selector sent to instance 0x1605a0'

It is occurring in cellForRowAtIndexPath: 它发生在cellForRowAtIndexPath中:

cell.videoName.width = 163.0;

where cell is a custom UITableViewCell and videoName is a UILabel. 其中cell是自定义UITableViewCell,而videoName是UILabel。 Why would the debug build work fine and release fail? 为什么调试版本可以正常工作并释放失败? Distribution build also fails. 分发版本也失败。 All are set for Base SDK == iPhone OS 3.0. 所有设置均针对基本SDK == iPhone OS 3.0。

To get a release build onto the phone, I'm simply changing my code signing to developer. 为了在手机上发布版本,我只是将代码签名更改为开发人员。 I've also tried the distribution build through iTunes but it fails with the same error. 我也尝试通过iTunes建立发行版本,但由于相同的错误而失败。

--- edit --- -编辑-

I'm loading the cell like this: 我正在像这样加载单元格:

static NSString * QuestionCellIdentifier = @"QuestionCellIdentifier";
TopicCellController *cell = (TopicCellController *)[tableView dequeueReusableCellWithIdentifier:QuestionCellIdentifier];

if(cell == nil){
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"TopicCell" owner:self options:nil];
    cell = [nib objectAtIndex:0];
}

cell.videoName.width = 163.0;

At runtime, the cell is of the custom type and videoName isn't nil. 在运行时,单元格为自定义类型,而videoName为nil。 If I remove the last line (setting width), it works fine. 如果我删除最后一行(设置宽度),则效果很好。

--- Edit: new discovery --- ---编辑:新发现---

I have found that rather than calling width, I can do this and it works in release: 我发现除了调用width之外,我还可以做到这一点,并且它在发布时有效:

cell.videoName.frame = CGRectMake(10, 10, 100, 30);

That really doesn't make any sense. 那真的没有任何意义。

In my experience this is usually because allocated memory is initialized to 0x00 in a debug build, and not in a release build. 以我的经验,这通常是因为在调试版本而不是发行版本中分配的内存被初始化为0x00 Therefore in the release build one of the members of your data structure has a selector that is leftover from something else. 因此,在发行版中,数据结构的成员之一具有一个选择器,该选择器是其他选择遗留下来的。 In the debug build it's set to zero. 在调试版本中,它设置为零。

But I don't know if the iPhone SDK environment initializes memory to zeroes--it seems that more modern development environments in a debug build initialize newly allocated memory to something like 0xcd instead of 0x00 . 但是我不知道iPhone SDK环境是否将内存初始化为零-似乎在调试版本中更现代的开发环境0xcd新分配的内存初始化为0xcd而不是0x00类的东西。

Also, you might want to check this StackOverflow question. 另外,您可能需要检查此StackOverflow问题。

It sounds like you have either got some debug code (tracing with NSLog?) that has side effects, or you have an intermittent race condition between threads that only appears in the faster release build. 听起来您要么具有一些副作用的调试代码(使用NSLog进行跟踪?),要么仅在较快发行版中出现了线程之间的间歇竞争状态。

So I would check firstly for debug-dependent code and then if you have any background threads check whether they might affect the cell. 因此,我将首先检查与调试有关的代码,然后检查是否有任何后台线程检查它们是否可能影响单元。

It might also be a bug in your cellForRowAtIndexPath reuse identifier processing that results in a nil sometimes - but it is difficult to see why this would only happen in release builds. 这也可能是您的cellForRowAtIndexPath重用标识符处理中的错误,有时会导致无效-但是很难理解为什么这只会在发行版中发生。 Without seeing how your custom cell is set up it is difficult to comment more. 如果不了解自定义单元的设置方式,则很难发表更多评论。

It should be: 它应该是:

cell.videoName.frame.size.width = 163.0;

UILabel doesn't have a width property, it has a frame property with a width field. UILabel没有width属性,它具有带有width字段的frame属性。

also the reason it is failing in release and not in debug is that release has some target build setting that is different than debug, see which ones are different. 这也是发行失败而不是在调试中失败的原因,是发行具有与调试不同的某些目标构建设置,请查看哪些是不同的。 usually release has more optimizations going on. 通常发布会进行更多优化。 and this will see the bug in your app, (like inlining code) where your bug in default target just happens to see a good spot in memory by bad luck on your part (or a blank spot, or just a spot that happens to have an integer in it, and that is what you were expecting) that isn't going to raise the exception, where inlining it moves the code so that your bug is now accessing someplace else in memory.. 这会看到您应用中的错误(例如内联代码),默认目标中的错误恰好由于运气不好而碰巧看到了内存中的好位置(或空白位置,或者恰好有一个整数,这就是您所期望的),不会引发异常,在该整数中对其进行内联可移动代码,以便您的错误现在可以访问内存中的其他位置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM