对象可能在被释放后被修改

Posted

技术标签:

【中文标题】对象可能在被释放后被修改【英文标题】:Object was probably modified after being freed 【发布时间】:2011-09-13 02:48:48 【问题描述】:

我正在 iPhone 上做一个项目。我现在从另一个 UIViewController 启动一个新的 UIViewController,然后在它们之间切换。这是我的代码。

iGreenAppDelegate *delegate = [UIApplication sharedApplication].delegate;
if(checkInViewController) 
    [checkInViewController release];
    checkInViewController = nil;

checkInViewController = [[CheckInViewController alloc] initWithCheckpoint:checkpoint];

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.8];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:[delegate window] cache:YES];
[[delegate rootTabBarController].view removeFromSuperview];
[[delegate window] addSubview:checkInViewController.view];
[UIView commitAnimations];

问题是我第二次启动UIViewController,我想释放它以避免造成内存泄漏。调试器显示

iGreen(916,0x3f60348c) malloc:对象 0x130350 错误:已释放对象的校验和不正确 - 。 在 malloc_error_break 中设置断点进行调试

这很奇怪,因为其他部分的类似代码不会返回此类错误。此外,我尝试了自动释放,但程序会立即崩溃,并且调试器说我正在修改最终层。

我整晚都在研究这个问题,但仍然对此感到困惑。

【问题讨论】:

顺便说一句,如果我不释放视图控制器,程序可以正常工作,但我认为这不是解决问题的好方法。谁能帮我找到问题 很难从这个 sn-p 中了解代码中发生的事情,但通常您只需要分配视图控制器,将其添加到标签栏控制器,然后释放视图控制器。标签栏控制器保留了视图控制器,因此它会一直存在。在我看来,您在标签栏控制器完成之前释放它。为了清楚起见,也许您可​​以在这个问题中添加更多代码? 你能添加你的 initWithCheckpoint 实现吗?另外,您是否尝试过在 Xcode 菜单中构建和分析? 【参考方案1】:

在 malloc_error_break 中设置断点进行调试。

这样做并发布回溯。

通常,这意味着您损坏了内存,但也可能意味着您有一个过度释放的对象。也可以尝试构建和分析。

【讨论】:

我该怎么做?如何在 malloc_error_break 中设置断点? @J.C.Leitão 运行 > 断点 > 添加符号断点 > 然后输入“malloc_error_break” @geekazoid,谢谢,我想这也会对其他人有所帮助... :) 在xCode 4.5.2中添加符号断点的步骤可以在here找到【参考方案2】:

除了在 malloc_error_break 中设置断点 - 在 xCode 中按 Command-6 以跳转到断点选项卡 - 还可以在您的方案中启用 malloc 辅助。

转到方案选择器,选择“编辑方案”找到“运行”目标并转到“诊断”选项卡。下面的内存管理启用 scribble、保护边缘、保护 malloc 和僵尸对象。

如果运气好的话,xCode 会发现你在分配的内存之外写入并损坏内存。

这就像处理记忆的成人监督......

【讨论】:

在调试时杀死性能以找到错误对我来说似乎没问题。【参考方案3】:

了解错误消息:它表示在您释放对象后,某些东西继续使用(和修改)该对象。这段代码释放了它,之后不再修改它,但你必须问还有什么可以继续使用它(不知道它已经被释放了)。

每次运行此 sn-p 中的代码时,它都会释放(释放)任何现有的 checkinViewController,并分配一个新的,显然它不会再接触旧的。但是还有谁可能拥有指向旧对象的指针?

可能是您编写的其他代码,也可能是 [delegate window],它通过“[[delegate window] addSubview:checkInViewController.view];”获取引用?希望后者有自己的引用,这意味着 release 不会立即释放它。

但要注意在不添加引用的情况下复制该指针的任何地方。如果你在某个地方这样做,然后在其他地方(例如上面的 sn-p)有人在同一个指针上调用 release,你现在可能有一个指向已释放对象的指针。

【讨论】:

【参考方案4】:

您的代码中有几处设计方面的问题。首先释放 checkInViewController 而不从其父视图中删除其视图(如果有),然后从其父视图中删除 rootTabBarController 的视图,而不对控制器本身做任何事情,并且不要将 checkInViewController 添加到 rootTabBarController 或 rootViewController 属性窗口,所以它在空中(只是由您当前的对象保留)。当这个(当前)对象被解除分配但 checkInViewController 的视图仍然放置(保留)在窗口上时会发生什么?

如果你释放你的 checkInViewController 但它的视图仍然被窗口保留,它可能会产生一些问题......

关于错误,我认为在某个地方对您的对象的弱引用(未保留)在它被释放后对其起作用。

【讨论】:

以上是关于对象可能在被释放后被修改的主要内容,如果未能解决你的问题,请参考以下文章

在objective-c中释放数组的内存问题

如何测试一个对象将在拆卸后被释放

当矩阵维数不是4的倍数时,如何避免AVX2的错误?

释放对象后调用方法?

如何允许在回调时释放对象?

UIViewController 在解除先前呈现的模态视图控制器后被释放