web-dev-qa-db-ja.com

Objective-C / iPhoneアプリで「クラシック」malloc()/ free()を使用しても大丈夫ですか?

私はしばらくの間iPhone開発をいじっていましたが、「ハードコア」の.NET開発者である場合は少し気まずい思いをしますが、慣れてしまえばそれほど悪くはありません。

Objective-Cについて読んだすべての本には、メモリ管理の保持/解放(参照カウント)についての話しかありません。昔ながらのC/C++開発者として、malloc()とfree()を使用して「通常の」方法を割り当てることについては、いくつかの脚注でのみ言及されているのは奇妙に思えます。

私はmalloc()とfree()がObjective-Cで機能することを知っていますが、それが一般的な慣行であるかどうか興味があります。結局、100個の整数の配列を割り当てたい場合、これが最も効率的な方法だと思われます。

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

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

// use the array

free(array);

これは確かに最良の方法ですか、またはプレーンなCメモリ管理を避けるべきですか?

53

Rawメモリの周りにはObjective-Cラッパーがあり、これを同様のタスクに使用するのが好きです:NSMutableData。所有権を保持/解放できるという利点に加えて、(自分で再割り当てを行わなくても)アレイを簡単に拡張できます。

コードは次のようになります。

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)
79
Nikolai Ruhe

Objective-CはCの厳密なスーパーセットであるため、プレーンなCを記述したい場合、それを妨げるものは何もありません。多くの場合、Objective-Cランタイムのオーバーヘッドを回避するために、mallocfreeを使用するのが有利です。

たとえば、不明な数の整数の配列を動的に割り当てる必要がある場合は、多くの場合より簡単で簡単です。

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

対:

_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];
_

私はiPhone用のWordゲームで作業していたので、有効な単語の数メガバイトの辞書をロードする必要がありました。 Wordリストは、malloc()で割り当てられた1つの巨大なchar配列にロードされ、メモリサイズをさらに削減するための巧妙な最適化が行われました。明らかに、このようなものでは、NSArrayを使用するオーバーヘッドは、限られたiPhoneでは完全に非現実的です。オーバーヘッドが正確にわからないが、それは確かに文字ごとに1バイト以上です。

48
Adam Rosenfield

もちろん、Objective-Cは単にCのスーパーセットであるため、これらの関数を使用しますcan。ただし、Objective-Cにはオブジェクトとこれは簡単です。

結局、上記のコードは次のように書くことができます。

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

//Use the array, adding objects when need be

[array release];

NSNumbersを格納するためにintオブジェクトを作成する必要がありますが(NSArrayでは非オブジェクトタイプを追加できないため)、一般的に使用するのが一般的ですオブジェクトの移動は簡単で、配列クラスは他のCocoaクラスとより一般的に統合され、メモリ管理は一般的に標準のCメモリ管理よりも簡単です。

また、配列にオブジェクトを追加または削除し始めると、Cocoa配列オブジェクトにより、これがはるかに簡単になります。

5
Alex Rozanski

標準のCタイプを扱っている場合、Cほど一般的ではないか「OK」です。Objective-Cの一部であるCでそれが行われます。

また、これらのオブジェクトの周りに何らかの種類のオブジェクトラッパーを記述して、Cocoaの残りの部分(KVO、メモリ管理など)と調和させることも珍しくありません。したがって、必要に応じて保持および解放できるように、舞台裏でmallocingを実行するIntArrayクラスを作成できます。これは厳密に必要というわけではないことに注意してください。そのような構造がプログラムの主要な部分である場合に便利です。

3
Chuck

Mallocを使用して自由に独自のメモリ管理を行うことはまったく問題ありません。実際にNSObjectのallocWithZone:は、mallocを使用してメモリを取得します。

2
Nikolai Ruhe