PDA

View Full Version : Array property




Miglu
Sep 11, 2010, 07:24 AM
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.



lee1210
Sep 11, 2010, 08:41 AM
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

PatrickCocoa
Sep 11, 2010, 08:41 AM
Show your code and it's more likely you'll get a reply.

Miglu
Sep 11, 2010, 08:58 AM
Thanks. So a C array property is not possible.

jared_kipe
Sep 11, 2010, 10:17 AM
@property (assign) int *array;

lee1210
Sep 11, 2010, 10:20 AM
Thanks. So a C array property is not possible.

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

jared_kipe
Sep 11, 2010, 11:27 AM
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

Agreed.

vocaro
Sep 12, 2010, 01:52 AM
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.

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.

vocaro
Sep 12, 2010, 01:56 AM
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?

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.

lee1210
Sep 12, 2010, 09:16 AM
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.



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.

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.

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

vocaro
Sep 12, 2010, 11:55 PM
The code above does not compile.

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

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.

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

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?

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.

chown33
Sep 13, 2010, 12:50 AM
Which is why stack-allocated arrays should not be assigned to a property.

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?


That doesn't mean a C-style array property "doesn't make sense", and it's certainly possible, contrary to what you were implying.

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).

lee1210
Sep 13, 2010, 08:01 AM
Of course not. Why are you statically allocating the arrays? You don't statically allocate an NSArray, do you? Apples to apples...

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.

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

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.

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.
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

vocaro
Sep 20, 2010, 11:54 PM
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?

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.

Post example code, please. I'm curious to see how you'd handle the lifetime issue lee1210 mentioned.

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


@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.

I'm also wondering how you'd ... reliably communicate the array's length (number of elements).

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.

vocaro
Sep 20, 2010, 11:56 PM
Of course not. Why are you statically allocating the arrays?
because that's what the OP was trying

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


Which is why stack-allocated arrays should not be assigned to a property.
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.


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"?

I said that arrays declared with a fixed size was not possible, because that's what the OP asked.

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

It's just ill-advised, which I am still convinced of.

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.

lee1210
Sep 21, 2010, 04:28 AM
Where did the OP say he was statically allocating the arrays?

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


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"?


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



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


They did, by way of the error.


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.

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