3

Example:

unsigned char colorComps[] = {2, 3, 22,   55, 9, 1};

Passing this to an Objective-C method which references it with a property. It needs to be copied to heap memory first. But is it fine to let the method do this step or must I copy it to heap before passing it to the method, for safety?

Proud Member
  • 40,078
  • 47
  • 146
  • 231
  • 1
    Isn't this the same as [your question from half an hour before](http://stackoverflow.com/questions/18105453/am-i-correctly-creating-and-passing-this-c-array-to-objective-c-method-and-refer/18105529#18105529)? –  Aug 07 '13 at 15:10
  • 1
    @ProudMember, H2CO3 is right, the questions are related. So it would help if you actually tell your _high level_ goal that you like to achieve. Maybe they way you want to do is unnecessarily complicated or even wrong. – DarkDust Aug 07 '13 at 15:15
  • @H2CO3 Looks like he's asking about my comment on that question. – Kevin Aug 07 '13 at 15:39

3 Answers3

3

In pretty much every C API I've used, the convention is that the called function is responsible for copying data if needed.

This makes sense, as the called function knows how long the data will be needed, whereas the caller doesn't. Since we generally use C for performance reasons, this also avoids unnecessary memory allocation and copying.

On that note, unless you've got performance reasons for using a C array, just use an NSArray of NSNumbers. Much simpler.

Chris Devereux
  • 5,453
  • 1
  • 26
  • 32
2

The exact same rules as with pass an array to a C function apply. There is no special handling in Objective-C regarding C arrays. Except that you can't declare a property with a C array type. For workarounds see this question and this question. In this case, your object (which wants to expose the array) should allocate the memory, copy the array and release it when appropriate. It's a bad idea to allocate it "outside" but then release it "inside".

Unless you really need a C array (for example, because you've got a third party library that wants it as argument and you'd need to construct it all the time) you should stick with Objective-C objects (NSNumbers in NSArrays). Especially since the syntax is now pretty straight forward:

NSArray *myArray = @[ @(1), @(42), @(543) ];

Using C arrays just "because they're faster" would be pre-mature optimization unless you have actually measured that an NSArray/NSNumber solution is a bottleneck for you. I'm doing multimedia processing on iOS and I've never had to switch from an NSArray to a C array for performance reasons.

Community
  • 1
  • 1
DarkDust
  • 90,870
  • 19
  • 190
  • 224
  • He's passing an array in that he wishes to assign to an object property. If the array was created on the stack, then yes, it will need to be copied to the heap, otherwise the pointer will be invalid once the stack frame holding the array data is popped. – BergQuester Aug 07 '13 at 14:53
  • Right, I missed the property part. Have updated the question. – DarkDust Aug 07 '13 at 15:02
  • Okay so it seems that it is safe to pass the array (on the stack) to a method which then copies it to the heap in order to hold a reference to it with an ivar or property? – Proud Member Aug 07 '13 at 16:04
  • @ProudMember Exactly. – DarkDust Aug 07 '13 at 16:10
2

I believe you're asking about my comment on your previous question, so let me explain.

If you simply take whatever array you receive and keep it as-is, you have no control over it; you're leaving the integrity of your code entirely to the calling function. You may accidentally forget to pass in a copy, or you pass in a string literal*, and then you have a potentially difficult-to-find bug. By using a property and setting the ivar to an array that you created, you are in control of it. You know precisely its desired lifetime, and you know it's safe (indeed, required) to free it in dealloc.

Note that this is the reason why block properties should always be declared copy. If you just keep the block around as you received it, it will be invalid and lead to problems later on unless it was already copied to the heap at some point. But you don't normally copy a block when you are passing it to a function, the function you call is responsible for making sure it's safe to keep around.

*: Yes, unlikely the way you're using it, but under different circumstances it could be a concern.

Community
  • 1
  • 1
Kevin
  • 53,822
  • 15
  • 101
  • 132