1. Welcome to the new MacRumors forums. See our announcement and read our FAQ

Array property

Discussion in 'Mac Programming' started by Miglu, Sep 11, 2010.

  1. macrumors member

    #1
    What is the correct way to make an array into a property? When I tried to do it like other properties, I got a "Bad property declaration" error.
     
  2. macrumors 68040

    lee1210

    #2
    A c-style array or an NSArray? The latter should be fine, the firmer doesn't make sense, because you can't change a fixed-dimension array with an assignment, etc. You could make a type *, but the memory management would not work.

    -Lee
     
  3. macrumors 6502a

    #3
    Show your code

    Show your code and it's more likely you'll get a reply.
     
  4. macrumors member

    #4
    Thanks. So a C array property is not possible.
     
  5. macrumors 68030

    jared_kipe

    #5
    @property (assign) int *array;
     
  6. macrumors 68040

    lee1210

    #6
    No. Think about what it would take to handle a set on this property. If you pass in another c-style array, what would you do? Copy the contents? How many bytes?

    You COULD have an int * property that you use to store the base of an array, but memory management would be a nightmare.

    -Lee
     
  7. macrumors 68030

    jared_kipe

    #7
    Agreed.
     
  8. macrumors regular

    #8
    Why would this not make sense? The only caveat is that the C-style array property would have to be declared as assign, not retain. Otherwise it's perfectly fine. There's no problem with it being fixed-dimension; an NSArray is fixed-dimension, too.
     
  9. macrumors regular

    #9
    Why are you making this so complicated? For an NSArray, setting the property doesn't copy the contents. You're just copying the array pointer itself. Same deal with a C-style array.
     
  10. macrumors 68040

    lee1210

    #10
    Code:
    
    int main(int argc, char *argv) {
      int x[5];
      int y[5];
      y[0]=3;
      y[2]=4;
      x=y;
    }
    
    
    I may not have been clear on what i meant by fixed-width array. I meant an array declared as above, with a width provided at declaration time. The code above does not compile. Arrays declared in this manner cannot be assigned to. It might not be exactly right, but i think of the base of these arrays as const. You can't change where the array points, just the contents stored there. If you were to @synthesize with assign, you'd get code similar to what I posted above. This won't work. NSArray is a totally different ball of wax, as there are clearly defined rules about the lifetime of
    the object by way of retain/release, etc.

    I don't feel that I am making anything more complicated than it is. If you were to declare an int * property, as jared_kipe and I mentioned, this is doable, but then memory management becomes terrible. If you use an automatic variable as shown in my example above to "set" the address of this property, once the stack frame the array was declared in is popped, this memory is being used for something else. It is very unlikely that your Object lifecycle is going to match up with a particular stack frame. If you pass in a dynamically allocated chunk of memory from malloc, now you have the issue of when to free that chunk. The next time something sets this property? How do you know that memory isn't in use somewhere else? Retain/release is a good way to manage memory, because you can lay claim to an object, and say when you're done, and when everyone is done the object can be destroyed. Without implementing your own system like this, you don't know when a particular chunk of memory from malloc can be free'd once it's tied to some objects. So now you have another lifecycle problem between this dynamic memory and your object.

    The fact of the matter is that the malloc/free system of memory management is very onerous, and if one can avoid mixing it with retain/release, they should.

    -Lee
     
  11. macrumors regular

    #11
    Of course not. Why are you statically allocating the arrays? You don't statically allocate an NSArray, do you? Apples to apples...

    Which is why stack-allocated arrays should not be assigned to a property.

    The fact that malloc/free requires a different style of management than retain/release is irrelevant. That doesn't mean a C-style array property "doesn't make sense", and it's certainly possible, contrary to what you were implying.
     
  12. macrumors 603

    #12
    How would the message receiver distinguish whether the array it receives as a parameter is stack-allocated or not? If it can't distinguish them, then how can it be written to work reliably?


    Post example code, please.

    I'm curious to see how you'd handle the lifetime issue lee1210 mentioned.

    I'm also wondering how you'd pass a C-style array as a property, and also reliably communicate the array's length (number of elements).
     
  13. macrumors 68040

    lee1210

    #13
    because that's what the OP was trying, and because it's a rather popular way to declare an array. A pointer in and of itself may be the base of an array or point to one value. I wouldn't see int * and say that it's an array. Also, in terms of length, you do statically allocate an NSArray. I'm guessing you meant heap-vs.-stack, which isn't even a question in Objective-C. Blocks are the only objects that can be stack-resident.

    You and I know that, but others might not. There are many new programmers in these parts who may not be aware of the pitfalls of passing a pointer to a stack-local variable to something that might outlive the stack frame.

    I said that arrays declared with a fixed size was not possible, because that's what the OP asked. This is true. Jared_kipe and I also stated that a pointer can be used as a property, to which the base of an array could be assigned. It's just ill-advised, which I am still convinced of. Mixing malloc/free and retain/release presents challenges above what one would face trying to do either independently. The proper handling all cases would be a bear. You may have a great solution in the bag already (which chown33 asked you to share), but most people don't.

    I don't think we disagree on the actual ability for one to do this, just on some of the semantics I used and the feasibility. I don't really care to belabor this longer, I hope my stance has been expressed. I think the OP has the answer they wanted, I was just trying to get them to think about things they may not have in the past. If you have much more experience, and are already aware of the challenges presented and how to overcome them that's excellent. I was trying to cater to those who may not be aware of these pitfalls.

    I feel like we are posting from opposite sides of the globe, really dragging this out chronologically. In any event, I always encourage discourse, but don't feel like this topic has many more crevices to explore. If I was terribly unclear in my original posts, that's unfortunate, and I will try to improve on this in the future. On the technical points of lifecycle management issues that arise I remain firm in my discouragement of mixing malloc/free and retain/release. If you have this solved correctly and completely, that is excellent, and certainly a cut above most of those seeking help here and I'd wager most of us providing it, myself included.

    -Lee
     
  14. macrumors regular

    #14
    But this memory lifetime issue also exists for NSArrays and reference counting. Let me turn the question around and ask: How would the message receiver know whether an NSArray it receives as a parameter isn't prematurely released by the caller? If it can't, then how can it be written to work reliably? For example, let's say there's an NSArray property marked "assign". A caller could set an NSArray to the property then immediately release it. Yikes!

    Of course, the answer to your question is that there must be some sort of agreement between caller and receiver on how to manage the memory pointed to by the property. This is true whether you're talking about NSArrays or C-style arrays. In the latter case, there would have to be some rule that says, if the array is stack-allocated, then the receiver of the property must have a lifetime no longer than the array's stack frame.

    There are many ways of handling the lifetime issue. Here's one:

    Code:
    @interface MyObject : NSObject {
        char *array;
    }
    @property (nonatomic, assign) char *array;
    @end
    
    @implementation MyObject
    @synthesize array;
    @end
    
    @interface MyAppDelegate : NSObject <NSApplicationDelegate> {
    	MyObject *object;
    }
    @end
    
    @implementation MyAppDelegate
    
    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    	object = [[MyObject alloc] init];
    	char *array = malloc(1024);
    	object.array = array;
    }
    
    - (void)applicationWillTerminate:(NSNotification *)aNotification {
    	free(object.array);
    	[object release];
    }
    
    @end
    
    Instead of the caller freeing the array, an alternative would be to have the receiver free it in the receiver's dealloc. It all depends on the agreed-upon protocol between caller and receiver.

    Again, there would have to be some agreement between caller and receiver on how this is done. Perhaps the property has some particular characteristic that gives it a constant length (e.g. a particular type of 2D matrix), and the receiver would be imbued with this constant. Or there could be a second property that provides the length (object.arrayLength = 1024). Or there could be a sentinel that indicates the end of the array (like C strings and their null terminators). There are many different ways.

    Now, if you say that all of this makes C-style arrays difficult, error-prone, and not worth the trouble, then I would certainly agree. But the OP wasn't asking whether to use C-style arrays. He just wanted to know how it could be done.
     
  15. macrumors regular

    #15
    Where did the OP say he was statically allocating the arrays?

    So? You can shoot yourself in the foot with the reference counting of NSArrays, too. New programmers (and old ones!) might call release once too often or retain once too often. Does that mean NSArrays as properties are "not possible"?

    No, the OP never mentioned anything about fixed-size arrays.

    I couldn't agree more. But "ill-advised" and "not possible" are two very different things. And in fact, you seem to have gotten the OP thinking that C arrays as properties are not possible at all. That's what I was objecting to.
     
  16. macrumors 68040

    lee1210

    #16
    By way of the error message. You get that with a fixed-size array, not with a pointer.

    I didn't say a pointer property was not possible, and actually posted this possibility in post #6.


    They did, by way of the error.

    I got them thinking that fixed-size arrays aren't possible, and mentioned a pointer as an alternative, but advised against it. Somehow I think we agree, but are still arguing. The only thing we are at odds on is if the OP was talking about fixed-size arrays, and the error message implies that they were.

    -Lee
     

Share This Page