【问题标题】:Objective-C and creating new object on the heapObjective-C 和在堆上创建新对象
【发布时间】:2012-02-14 15:32:15
【问题描述】:

我是 Objective-C 编程的新手,在尝试在方法中创建对象时遇到了一些麻烦。该程序的目的是提供一种表示有向图的方法,稍后我将使用它来测试图论。

问题。

//From GraphObject.m
-(void) addNode
{
    GraphNode *newNode = [[GraphNode alloc] initWithId:count];
    [graphNodes addObject:newNode];
    NSLog(@"Node %i added", count);
    count++;
}

这段摘录来自我的 GraphObject 类,是程序中断的地方。它在块的第一行中断。 该方法旨在创建一个 GraphNode 对象并将其放入 GraphObject 类的 NSMutableArray(名为 graphNodes)中。 count 变量只是跟踪添加了多少节点。 习惯了 C++ 我很难理解为什么它不只是将对象放在堆上,而是让我使用它。顺便提一句。如果我把它放在我的 main 中,完全相同的行可以正常工作,这让我有点失望。

如果有人能解释我做错了什么,将不胜感激。

编辑: 这是 initWithId 方法。我开始怀疑原因可能在这里。它必须返回一个指向自身的指针吗?

-(id) initWithId:(int)n
{
    nodeId = [NSNumber numberWithInt:n];
    neighbourNodes = [NSMutableArray arrayWithCapacity:8];
    return self;
}

您提到的内存泄漏(yAak),我假设它与在此方法中创建 GraphNode 数组有关。但是,当我删除要放入它们的数组时,这不会解决吗?如果我用相同的方法删除它们,就我所见,数组中不会有任何东西。另外,我很抱歉没有发布任何错误消息,因为我是 xcode 的新手,但我根本看不到任何错误消息。构建成功,它只是说程序在代码中的某一行停止。

EDIT2(和解决方案):嗯,这是一个奇怪的惊喜。我删除/剪切了代码并运行了一次程序,然后将完全相同的代码粘贴回去,现在它工作正常。那是一个稳定的IDE。再次感谢您的回复,我相信我很快就会回到这里。

【问题讨论】:

  • 发布错误时遇到的错误。我在这里看到的所有错误都是潜在的内存泄漏,这不会导致中断。
  • 你能发布-[GraphNode initWithId:]的实现吗?另外,请发布您看到的错误消息。您发布的代码没有任何不正确的地方。

标签: objective-c heap-memory


【解决方案1】:

Leaks、NSZombies 等都是有用的工具。但是当特别是。当您不熟悉该语言时(有时即使您不是),解决此类内存管理问题的最佳方法是:

1) 阅读以下内容: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html

2) 再次查看您的代码。

3) 重读: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html

[...等]

在这种情况下,由于您没有获得 NSNumber 对象的所有权,因此它在应用程序运行循环的下一个循环之前被释放。

这在 main 中没有发生,因为您在应用程序的 runloop 之外并且没有自动释放池(您可能收到一条控制台消息,说对象泄漏是因为没有自动释放池)。如果您不确定那是什么,请阅读链接文档中有关自动释放池的部分。

【讨论】:

    【解决方案2】:

    你的初始化器:

    -(id) initWithId:(int)n
    {
        nodeId = [NSNumber numberWithInt:n];
        neighbourNodes = [NSMutableArray arrayWithCapacity:8];
        return self;
    }
    

    应该是这样的:

    - (id)initWithId:(int)n
    {
        self = [super init]; /* << or whatever the designated initializer of the superclass is */
        if (nil != self) {
            nodeId = [[NSNumber alloc] initWithInt:n];
            neighbourNodes = [[NSMutableArray alloc] initWithCapacity:8];
        }
        return self;
    }
    

    就堆而言,您创建的每个 NSObject 实例都被引用计数并在堆上。 Clang 甚至不允许您在堆栈上创建 objc 对象(GCC 会)。

    当你认为你的堆被弄乱了或者你的对象或它们的成员被过早地释放时,请记住有很多内存/引用计数诊断工具:Zombies 是一个,GuardMalloc 和 scribbling 是其他的。当然,Leaks 也是一个不错的检查。

    【讨论】:

    • 谢谢,我也会解决这个问题的。
    猜你喜欢
    • 2014-01-06
    • 2010-12-08
    • 2016-10-23
    • 1970-01-01
    • 2011-06-25
    • 2013-09-22
    • 1970-01-01
    • 1970-01-01
    • 2015-10-29
    相关资源
    最近更新 更多