简体   繁体   English

在我的Objective-C代码中间接调用时,为什么这个C数组为NULL? (cocos2d的)

[英]Why is this C array NULL when indirectly called in my Objective-C code? (cocos2d)

i have two Objective-C classes, say ParentLayer and ChildLayer. 我有两个Objective-C类,比如ParentLayer和ChildLayer。 in my child instance, i want to access a C-Array in my parent instance. 在我的子实例中,我想在我的父实例中访问一个C-Array。 so i have something like this in my cocos2d code: 所以我在cocos2d代码中有这样的东西:

#define kNumOfElements 10
@implementation ParentLayer{
    int array[kNumOfElements];
}
-(id)init{
    //...
    for(int i=0;i<kNumOfElements;i++){
        array[i] = i;
    }
    [self addChild:childLayer];
    [childLayer initializeValues];
    //...
}
-(int *)getArray{
    return array;
}
@end

//meanwhile in my child layer...
//...
-(void)initializeValues{
    int *arr = [(ParentLayer *)[self parent] getArray];
    //NSLog(@"%d",arr[0]);   <------- this gives you bad exec access point, and looks like it's 0x00 for memory address
}
//...
  • what's the proper way to do this? 这样做的正确方法是什么?
  • maybe i dont understand the right memory management behind C Arrays. 也许我不理解C阵列背后的正确内存管理。 i was under the impression that C Arrays didn't need to be allocated, and that they could be passed by value, on the stack? 我的印象是C阵列不需要分配,并且它们可以在堆栈上通过值传递?
  • also, shouldn't my parent instance still be around? 另外,我的父实例不应该还在吗? i thought if i put a C Array as an ivar of my parent, it shouldn't get destroyed 我想如果我把一个C数组作为我父母的ivar,它不应该被破坏

any help is appreciated. 任何帮助表示赞赏。 thanks! 谢谢!

In Objective C , you can use property for this. Objective C中 ,您可以使用属性。

#define kNumOfElements 10

@interface  ParentLayer: NSObject
{
    int *array;
}
@property(nonatomic, assign) int *array;
@end

@implementation ParentLayer
-(id)init{
    //...
    self.array =(int*)malloc(sizeof(int) * kNumOfElements);

    for(int i=0;i<kNumOfElements;i++){
        self.array[i] = i;
    }
    [self addChild:childLayer];
    [childLayer initializeValues];
    //...
}
//-(int *)getArray{
//    return array;
//}

-(void)dealloc
{
   if(self.array)
   {
      free(self.array); self.array = NULL;
   }
   [super dealloc];
}    

@end


-(void)initializeValues{

    ParentLayer *player = (ParentLayer *)[self parent] ;
    int *arr = player.array;
    //NSLog(@"%d",arr[0]);   <------- this gives you bad exec access point, and looks like it's 0x00 for memory address
}

what's the proper way to do this? 这样做的正确方法是什么?

Ideally, you should never pass a C-style array pointer outside of the object that owns it. 理想情况下,您永远不应该在拥有它的对象之外传递C风格的数组指针。 You open yourself up to all sorts of problems if a piece of code tries to use the array after the object is deallocated, or writes past the end, or something else. 如果一段代码在取消分配对象后尝试使用数组,或者在结束时写入或其他内容,则可以解决各种问题。 It is easier to guarantee that none of this happens if you can make sure the reference never leaves the object's source file. 如果可以确保引用永远不会离开对象的源文件,则更容易保证不会发生这种情况。

maybe i dont understand the right memory management behind C Arrays. 也许我不理解C阵列背后的正确内存管理。 i was under the impression that C Arrays didn't need to be allocated, and that they could be passed by value, on the stack? 我的印象是C阵列不需要分配,并且它们可以在堆栈上通过值传递?

It is not that simple. 事情并非那么简单。

A C-style array is just a memory address. C风格的数组只是一个内存地址。 That's it. 而已。 It doesn't carry around the other useful information that an object might, such as number of elements, retain count. 它不携带对象可能的其他有用信息,例如元素数量,保留计数。

If you declare an array like this: 如果你声明一个这样的数组:

int array[100];

Then the memory is allocated in either the stack or the heap, depending on where you put the declaration. 然后根据放置声明的位置在堆栈或堆中分配内存。 If it's a local variable inside a function or method, it's on the stack. 如果它是函数或方法中的局部变量,它就在堆栈中。 If it's in global scope or a member variable of an object, it's on the heap. 如果它在全局范围或对象的成员变量中,则它在堆上。

Furthermore, if it's an instance variable, you're actually setting aside 100 ints worth of memory inside the block of memory allocated to hold the object. 此外,如果它是一个实例变量,那么实际上是在分配用于保存对象的内存块中预留了100个内存。 It isn't a separate thing. 这不是一个单独的事情。

Since array is just a memory address, you are basically passing it around by reference. 由于array只是一个内存地址,因此您基本上是通过引用传递它。 Technically, you are passing the address by value, but any changes you make to the memory will be seen by anyone looking at the same address, so it acts like pass by reference. 从技术上讲,您按值传递地址,但是对于查看相同地址的任何人都会看到您对内存所做的任何更改,因此它的作用类似于按引用传递。

also, shouldn't my parent instance still be around? 另外,我的父实例不应该还在吗? i thought if i put a C Array as an ivar of my parent, it shouldn't get destroyed 我想如果我把一个C数组作为我父母的ivar,它不应该被破坏

The way you have coded it, that array will be valid as long as the parent object is around. 你编写它的方式,只要父对象在周围,该数组将是有效的。 Once the parent gets deallocated, that memory could be reclaimed. 一旦父节点被释放,就可以回收该内存。 Since the array variable is just a memory address, however, you have no way of knowing whether the data it points to is valid or not. 但是,由于array变量只是一个内存地址,因此您无法知道它指向的数据是否有效。 This is the danger of using C-style arrays rather than objects. 这是使用C风格数组而不是对象的危险。

Since the last line is giving you NULL (0) address, my guess is that [self parent] is nil. 由于最后一行给你NULL(0)地址,我的猜测是[self parent]是nil。 That would put a 0 in arr ; 那将是一个0 in arr ; when you try to dereference NULL, you will get an exception. 当您尝试取消引用NULL时,您将获得异常。

can't seem to add a reply to benzado's post. 似乎无法添加对benzado的帖子的回复。 but depending on how to declare your object, it might be automatically deallocated. 但是根据如何声明对象,它可能会自动释放。 to ensure that it is retained, use a retain keyword. 要确保保留它,请使用retain关键字。

[obj retain];

especially using the cocos2d framework, they have quite a number of auto release objects. 特别是使用cocos2d框架,它们有很多自动释放对象。 typically initWith shouldn't be auto release. 通常initWith不应该是自动释放。

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

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