2010-11-12 84 views
1

这不是原始代码(我试图简化调试时剥离了一些东西),但它确实显示了问题。在它面前,看起来很简单:为什么传值结构参数被破坏?

- (void) testMethod: (TouchData) toi { 

    TouchData newToi = toi; 
    NSString *test = @"test string"; 
    NSLog(@"string: %@", test); 

    // in ‘real’ code I pass the struct back 
    // It’s void here for the simplest possible 
    // case 
} 

TouchData是一个结构,从而宣告:

typedef struct { 
    Entity *owner; 
    CGPoint startPos; 
    CGPoint latestPos; 
    CGPoint startOfStraightSwipePos; 
    NSTimeInterval startTime; 
    NSTimeInterval latestTime; 
    NSTimeInterval startOfStraightSwipeTime; 
    CGFloat latestSpeed; 
    NSMutableArray *gestures; 
    BOOL isOfInterest; 
} TouchData; 

当我通过TestMethod的在调试步骤(看TOI)上打的NSLog(甚至不涉及toi),所有toi成员值突然消失。这不会发生在副本(newToi)上。如果我通过引用传递结构,则不会发生这种情况。如果直接用方法体替换testMethod调用(即,如果我现场运行这些行而不是调用方法),则不会发生这种情况。如果我将toi参数类型更改为具有几个int成员的虚拟结构体(在调用之前创建),则不会发生这种情况。

可能值得指出的是,testMethod仅在其自己的 类中调用,并且调用方刚刚从NSMutableDictionary中提取了结构(通过拆开NSValue)。但考虑到(a)结构是 在这里通过值传递给方法,和(b)在入口处它的成员如 由调试器完全符合预期,我没有看到这可能导致问题。在结构中还有两个对象指针的棘手问题,但在其他上下文中,他们正在确定,并且在调试器中检查该方法的入口,所以我不认为我已经错过了基本保留。

我想我遇到了某种堆或堆栈腐败,但我不知道如何或为什么。我是Objective-C的新手,之前曾在 垃圾收集环境中工作,所以我的内存管理经验有限。我完全有可能错过了一些显而易见的事情。

我希望有人会告诉我让TouchData成为一种对象类型,事实上我可能会那样做。我也有一些测试过的解决方法,即。要么在副本上工作,要么在ref中传递结构。但我真的很想知道这里发生了什么。

+0

在原始方法中,您的返回值是否损坏? – Ryan 2010-11-12 05:31:14

+0

这是,我认为它一定是一个内存管理问题。但我很确定简化代码中发生的事情是不同的,正如Yuji在下面解释的那样。我已经将TouchData重新实现为一个类,它更直接地工作。 – Cris 2010-11-13 02:52:09

回答

2

如果在线TouchData newToi=toi之后没有使用toi,则编译器可以在栈内存中执行任何想要执行的操作,其中toi最初放置在该行之后。例如,它可能会在调用另一个函数时重用堆栈内存,在此例中为NSLog

因此,通过调试器看toi可能会显示一些奇怪的东西。编译器通常会做这些事情,特别是如果开启优化。即使没有优化,也不能保证toi的堆栈位置在上次使用后保持不变。

顺便说一句,你说toi里面的对象指针并没有引起问题,但这是一个棘手的情况,我强烈反对这种做法。遵循标准的保留/释放规则;否则,另一位看看你的代码的程序员(可能是两年后你自己)可能会完全困惑。此外,静态分析器(可通过在XCode中执行Build &分析进行访问)可能会造成混淆,并可能导致误报。所以,不要这样做。

+0

是的,谢谢,当然。我得到的原始“腐败”是不同的 - 结构字段疯狂出现各种垃圾(当在调试器或NSLog输出中看到时)。这看起来像真正的记忆腐败。在简化过程中,我实际上已经创造了一个不同的问题(即,正如你所解释的),我已经(已经疲惫地)把它看作是同一件事,这已经足够接近了(将字段清零而不是疯狂的值)。 – Cris 2010-11-13 02:44:51

+0

我已将TouchData重新实现为类bt。是一个过早优化的例子;也没有预见到,看起来只是一堆数据会扩大到包括它的行为方式。 – Cris 2010-11-13 02:54:28