views:

3377

answers:

5

I've been playing around with iPhone development for a while, and although it feels a bit awkward when you're a "hard core" .NET developer, it's not all that bad once you get used to it.

In every book I read about Objective-C, there's only talk about retain/release (reference counting) for memory management. As an old-skool C/C++ developer, it seems strange that allocating the "normal" way, using malloc() and free() is only mentioned in some footnotes.

I know that malloc() and free() work in Objective-C, but I'm curious if it is common practice or not. After all, if I want to allocate an array of 100 integers, it seems that this is the most efficient way to do it:

int *array = malloc(sizeof(int) * 100);

memset(array,0,sizeof(int) * 100);

// use the array

free(array);

Is this indeed the best way, or should I avoid plain C memory management?

+2  A: 

It's perfectly fine to use malloc and free to do your own memory management. Actually NSObject's allocWithZone: uses malloc to get the memory.

Nikolai Ruhe
It's technically calloc, but yeah. =)
Dave DeLong
Actually, it's technically `NSAllocateObject()`. What happens next is more complicated.Under ObjC2 w/ GC enabled, `NSAllocateObject()` calls `objc_allocate_object()`.Under ObjC2 w/o GC, or ObjC < 2, `NSAllocateObject()` calls `class_createInstanceFromZone()`, which in turn calls `malloc_zone_calloc()`, which, as its name implies, is logically equivalent to `calloc()`. A `calloc()` with a `count` of `1` is by definition indigistqushable from an allocation obtained by `malloc` of the same `size` that has had its `space is initialized to all bits zero` (C99 7.20.3.1.2).
johne
so..what Dave said?
Typeoneerror
+3  A: 

Of course, you can use these functions, because Objective-C is merely a superset of C. However, it is fairly uncommon to do this sort of thing, since Objective-C contains objects and ways to make this easier.

After all, you could write the above code as:

NSMutableArray *array = [[NSMutableArray alloc] init];

//Use the array, adding objects when need be

[array release];

Although you would have to create NSNumber objects to store the ints (since NSArray doesn't allow non-object types to be added), it is generally more common to use objects, because it is easier to move data around, and the array classes are integrated more commonly with other Cocoa classes, and the memory management is generally more straightforward than standard C memory management.

Also, if you start adding or removing objects from the array, then the Cocoa array objects make this much easier to do.

Perspx
This seems like overkill if you need a simple array of integers. Especially the need to create NSNumber objects seems so inefficient to me. What if I want to allocate an array of 100,000 booleans?
Philippe Leybaert
Perhaps, there may be a slight overhead compared to using simple arrays of integers. But they are certainly more commonly used than using C memory management. And if you are allocating an array of 100,000 booleans then there may be a better way to do it than how you are currently implementing it (unless that's a hypothetical scenario).
Perspx
This is especially overkill if you're dealing with really simple objects. For example, if you were to build MineSweeper for the iPhone, it is *orders of magnitude* faster to have a square be a struct and malloc an array of structs than to create the squares as objects and put them in an NSArray. Plus, you'll use quite a bit less memory.
Dave DeLong
Of course, it depends on the context of the question, but using standard C memory management is fairly uncommon. Also, as I said, they can become more useful if you are manipulating the array items.
Perspx
I, too, disagree that it is not common. It depends very much on the problem domain. For example when using C libraries (like OpenGL, which is very common) you have to dig into C memory management. Plus it is far more efficient for large arrays pod types.
Nikolai Ruhe
+5  A: 

It's perfectly fine -- Objective-C is a strict superset of C, so if you want to write plain C, there's nothing preventing you from doing so. In many cases, it's advantageous to use malloc and free to avoid the overhead of the Objective-C runtime.

For example, if you need to dynamically allocate an array of an unknown number of integers, it's often simpler and easier:

int *array = malloc(N * sizeof(int));  // check for NULL return value!
// use array[0]..array[N-1]
...
free(array);

Versus:

NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:N];
// use NSMutableArray methods to do stuff with array; must use NSNumbers instead
// of plain ints, which adds more overhead
...
[array release];

I was working on a word game for the iPhone, and we had to load a multi-megabyte dictionary of valid words. The word list was loaded into one giant char array allocated with malloc(), with some clever optimizations to reduce the memory size even more. Obviously for something like this, the overhead of using an NSArray is completely impractical on the limited iPhone. I don't know exactly what the overhead is, but it's certainly more than one byte per character.

Adam Rosenfield
RE: 'strict superset'. While I personally (strongly) agree with you, since we're discussing Apple/iPhone development, this statement is not technically true. Apple defines it thusly: `Objective-C syntax is a superset of GNU C/C++ syntax`. Strict superset has a very specific meaning, with the unqualified use of superset being the lesser of the two (think "behaves like" vs. "exactly like"). The qualifier of `syntax` further restricts it to the point where it is almost useless, effectively limiting Apples obligation to Annex A of the C99 spec- a scant 16 pages out of 552 in the standard.
johne
+1  A: 

If you're dealing with standard C types, it's no less common or "OK" than in C. That's how it's done in C, which is a part of Objective-C.

It's also not unusual to write some kind of object wrapper around these things to bring it into harmony with the rest of Cocoa (KVO, memory management, etc.). So you might create an IntArray class that does the mallocing behind the scenes so you can retain and release it as needed. Note that this isn't strictly necessary — it can just be handy if that kind of structure is a major part of your program.

Chuck
+3  A: 

There's an Objective-C wrapper around raw memory which I like to use a lot for similar tasks: NSMutableData. It has the benefit of giving you retain/release ownership plus it can grow the array easily (without having you to do the realloc yourself).

Your code would look like:

NSMutableData* data = [NSMutableData dataWithLength:sizeof(int) * 100];
int* array = [data mutableBytes];
// memory is already zeroed

// use the array

// decide later that we need more space:
[data setLength:sizeof(int) * 200];
array = [data mutableBytes]; // re-fetch pointer in case memory needed to be copied

// no need to free
// (it's done when the autoreleased object is deallocated)
Nikolai Ruhe