2011年5月28日土曜日

Objective-Cのメモリ管理はそんなに難しくはない(理論編)

Objective-C(非GCの場合)のメモリ管理は癖があってわかりづらいと聞いていたのですが、
実際にiOS開発でやってみたところ特にそうは感じず、むしろCとかC++よりは親切にすら感じました。

自分の理解の範疇でObjective-Cのメモリ管理について説明してみます。

ここでは一貫性を持たせるためにオブジェクトではなく、クラスオブジェクトとしてインスタンスという言葉で統一して使います。
また、allocを伴わない生成、autoreleaseについてはここでは触れず別途実践編で触れていきたいと思います。

インスタンスの生成・削除は基本的には全く同じ

・C++の場合
生成・・・new
削除・・・delete

・Objective-Cの場合
生成・・・alloc して init(またはnew)
削除・・・release (厳密にはreleaseの中でdeallocが呼ばれます※)
※なぜdeallocじゃないのかは後ほど説明します。

Objective-Cではallocではインスタンスを生成するだけで、初期化はinitでやるという点が違うくらいでほぼ一緒です。

ただし、実際にインスタンスが削除されるのはreleaseを呼んだ時点とは限らないというところがポイントになります。
これが混乱を巻き起こしていると思われます。
これを理解するには、なんでそんな作りになってるのということを理解する必要があるかと。

なぜObjective-Cでは、C/C++と同じやり方ではなく、後ほど説明する「retainカウント」という独自の方法をとったのでしょうか。

C/C++におけるメモリ管理の問題

まずはC/C++のメモリ管理のやり方ではどこがまずいのかを考えてみます。
  • 確保したメモリをどこが開放すべきなのか不明確である
これが一番の問題だと思っています。
インスタンスを生成した場合に、生成した人(クラス)が削除すれば問題ないわけですが、大抵の場合そうではなく、クラスのインスタンスのポインタをたらい回しにしているうちに、あれ、これってどこで削除するんだっけということになり、削除し忘れが起こったり、複数の箇所で削除しようとして落ちるといったメモリ関連の不具合が発生します。

これを解決するには、生成したものをどこで削除するかといったことの「決め事」を作る必要があります。そのやり方は様々あり、プログラムに求められる性能とかにもよるのでプロジェクトによって違います。
共通していることは、決め事は「プロジェクト毎に決める」ということで「言語仕様としては決められていない」という点にあります。

よく言うと柔軟な言語仕様ですが、悪く言うと無法地帯を産み出しているとも言えます。

Objective-Cのメモリ管理

そこで、Objective-Cではインスタンスの生成・削除の責任をはっきりさせるために、「オーナーシップ」という考え方のもと設計されています。

Objective-Cのオーナーシップとは、簡単に言うと、所有者が責任を持って削除するということです。

このオーナーシップを実現するために「retain」と「release」が存在します。

「retain」は、このインスタンスを所有しますという宣言みたいなもので、retainを呼ぶことにより、所有者となります。
また、インスタンスの生成であるallocしたときは自動的にretainされるので、allocを呼ぶことでも所有者になります。
所有者が「release」することにより事実上削除したことになります

インスタンスを所有している人がだれもいなくなったら、ようやくその時になって初めてインスタンスは実際に削除されます。(上で事実上と書いたのはこのためです)
ここが実際にインスタンスが削除されるのはreleaseを呼んだ時点とは限らないわけになります。
なのでreleaseでなく、いきなりdeallocを呼んでしまうとまだ削除できる状態でないのに、deallocの終了処理が動いてしまうという問題があるので、deallocは使ってはいけません。

オーナーシップでは、所有者、つまりはinitした人とretainした人は、かならずreleaseしなければなりません。もしそうしなければretainとreleaseの対応関係が崩れてしまい、メモリリークや不正メモリアクセスが発生します。

Objective-Cでのこのオーナーシップの実装は「retainカウント」という方法で実現されています。
インスタンス毎にretainカウントというカウンタを持っていて、alloc時に1になり、retainされたら1を加算して、releaseされたら1を減算し、0になったら削除するという単純なものです。セマフォみたいなものです。

オーナーシップの副作用

オーナーシップにより、メモリの確保・開放が明確になり、素晴らしいことでありますが、もちろんこれによる副作用もあります。

それは主にプログラムの速度に影響します。

retainカウンタというのを制御しているので、C++に比べると余計な処理をやっていることとなります。retain,releaseの呼び出しによる余計なオーバーヘッドももちろんありますので、retainカウンタ有り無しでは性能に違いが現れます。

オーナーシップはあくまでポリシーでしかない

前述で「所有者、つまりはallocした人とretainした人は、かならずreleaseしなければなりません。」と書きましたが、これはあくまで「ポリシー」でしかありません。

つまり、initした人とretainした人がreleaseを呼ばなくてもコンパイル時にエラーになったりはしません。
プログラムの書き方次第では、

ClassA* objA = [[ClassA alloc] init];
ClassB* objB = [[ClassB alloc] init];
[objA send:objB];//ClassAのsendメソッド内で引数のobjBをretainする.
[objB release];//ClassAでretainしたのをここでrelease.
[objB release];
[objA release];

なんてことも動きさえすれば、平気でできてしまいます。

なので、いくらObjective-Cでオーナーシップの仕組みを提供していても、プログラマがちゃんと理解せずに使っていると、ただの読みづらいコードやカオスなコードになります。
そういう使い方をするのであれば、retain、releaseを使うのは放棄し、alloc,deallocでどうにかすべきだと思います。(ライブラリを使うことも放棄することになりますが・・)
まぁそれだったらCで書いたほうがいいですね。。

Objective-Cのメモリ管理がどうのこうのと文句を言っている人がいたら、これに当てはまっている危険性があるのでよくコードを見てあげたほうがいいと思います。


つまりはどんな道具(言語)も使い方次第です。
是非Objective-Cユーザーはオーナーシップを理解し、よいコードを書いていきましょう。

-----------------------------------------------------------------------------------------------------------
嘘とか間違いなど指摘していただけると幸いです。

Objective-Cの理解に役立つ本

11章にObjective-Cの設計者との談話が載っています。



Objective-Cの言語の本はこれしか読んだことがないので・・。

2011年5月27日金曜日

アジャイル

MIT Media Labの新所長になられた伊藤穰一さん(@joi)とアジャイルで開発しているPivotalのCEOのIan McFarlandさんのアジャイルスタートアップについての講演に参加してきました。
伊藤穰一とPivotalのIan McFarlandが語る「アジャイルスタートアップ」
http://www.ustream.tv/recorded/14985986

感想

現状のWeb界隈のスピードの速さを見るとアジャイル開発の重要性は明らかに感じられます。これまでの1年かかるようなものづくりのやり方では絶対勝てません。
ただペアプログラミングまで必要かは議論がわかれるとは思いますが、ストーリーベースでテストを行いContinuous Releasabilityを確保するのは必須だと思います。

アジャイルといっても今よりずっと前から言われていますが、うまく普及していないのは、これまでの考え方を捨てて、発想を転換しなければならないということだと思っています。
特に経営レベルでは、これまでの仕様と納期ありきから脱却しなければならないわけですから。エンジニアを信用して投資するなんてことは、リスクの高い責任を背負うことになるので到底今の日本の大企業ではできないでしょう。
アジャイルを本気でやるにはトップダウンで決定し、宗教的に信じこんでやるのが一番な気がします。そういう点でPivotalはうまくいっているんだろうなと。

また我々組み込み業界だと度々ソフトを更新ってわけにもいかないわけで、この先生き残っていくには、「ソフトの更新がバリバリできる環境」をつくることが肝なのではないかと思います。国としてもものづくり日本とか言っているのであれば、こういったところのインフラを作ってほしいものです。

メモ

・アジャイルは元々は日本の製造業のやり方から来ている
・基本的な方向性は決めるが最終目的をあまり決めず、数日から2週間のスプリント毎にユーザのフィードバックももとに、なにをやるか見直す
・例えばYouTubeはもともと出会い系の動画サイトを目指していたり、Flickerはもともとはゲームだったりとやっているうちにゴールは大きく変わっている
・プロセスは、ストーリー単位(ストーリーは文書で書きだす)⇒テストを書く⇒コーディングする⇒テストをパスする
・ソースコード:テストコードの割合は1:1.5くらい
・朝きてストーリーカードをみてみんなでどれをやるか決める
・PMはいらない
・いつまでに何をではなく、このスピードでいけばここまでできるというスタイル
・締切りに向かってガッとやるのではなく無理のないペースで
・4〜6人のチームで必ずペアプログラミング
・プログラミングのうち8割くらいは悩んでたりするので2人でやったほうが効率的
・技もコードも覚えられるので新しい人が入ってきた場合にも育てやすく入れやすい、新人を入れるサイクルを回せる
・コードはシンプルに書く。コードでイノベーションを起こそうとしてはならない。それはストーリーでやるべき
・絶対にプロトタイプは製品化しない。つくり直す
・テストドリブンで常にリリースできるものをつくり、短いサイクルでストーリーを実現していくので、常に新しいものがリアルタイムに出すことができる
・FacebookやTwitterは大きい会社になってもほぼ毎週のようにころころ機能が変わっているので、うまくプロセスをまわしている。
・ソースコードや特許はアジャイルにとっては負債。捨て難いから。
・プロセスの一員としてデザイナーを入れる。デザインもカリスマデザイナーが作ったものをそのまま作るようなやり方ではなく、常に仮説としてユーザーの意見を取り入れて変更する。
・日本のモノづくりは仕様を決めてから作り始めできあがるのに1年くらいかかるが、それでは遅い。世の中は毎日めまぐるしく変わっているのに1年後にユーザーが何がほしいのかはわからない。
・経営レベルで発想を変えないといけない。その点ではベンチャーのほうがやりやすい。
・アメリカではとてもデータドリブン。ユーザの動きといったデータを細かく分析して仮説を検証している。
・データに頼りすぎてもだめだが、データを無視して同じ失敗を繰り返すのもだめ。そのバランスが重要

その他

講演とは関係ないですがアジャイルつながりで。

今日見つけた記事でScrumやXPなどのアジャイルプラクティスをミックスしてやるといったことについて書かれています。

アジャイル・ブッフェへのいざない(MSのエバンジェリストの長沢さん)

本では、こちらの本の前半部分にアジャイルプラクティス(extreme programing)の説明がわかりやすく書いてあります。

2011年5月14日土曜日

ブラウザでAngry Birds

iPhoneやAndroidアプリで有名なAngryBirdsがブラウザ上でもプレイできるようになりました。

http://chrome.angrybirds.com/

ただしまだβ版なのでバグは結構ありそうです。
私も試してみましたが、
2011/5/14現在でChrome11だと2-9がプレイできないのとHD版も動きません。

気になったニュース

最近ろくなネタがないなと思っていたら突然色々と湧いてきました。
多いので五月雨式に。


NVIDIAがベースバンドプロセッサのIceraを買収してモバイル市場の脇役から主役化へ踏み出す
http://jp.techcrunch.com/archives/20110509nvidia-buys-baseband-and-rf-technology-company-icera-for-367m-in-cash/
Iceraってのは知らなかったですが、ベースバンドプロセッサ側も手に入れたのは大きいのでは。Android市場ではNVIDIAががんばりますという感じがしています


マイクロソフト、手のひら全体を使うタッチUIを研究中
http://jp.techcrunch.com/archives/20110509microsoft-research-looking-into-better-whole-hand-touchscreen-gestures/

マイクロソフトはKinectだけでなくこういうのも開発してたんですね。
さすが、膨大な資金力があるだけあってこれまでの研究に当ててきたのが生きてるのかも。


Apple が x86 から ARM に移行予定 ?
http://slashdot.jp/apple/article.pl?sid=11/05/10/0114242

ラップトップでARMというのはうーんという感じがしますね、それだとほんとにネットブックになってしまいそうな気が

2011年5月11日水曜日

Google I/O関連ニュース

Google I/Oが開催中でGoogle関係のニュースで溢れてます。

Androidは3.1 IcecreamSandwitch の発表がきました。
があまり変わってないっぽいですね・・

「タブレット向け『Honeycomb』の機能をあらゆる端末に」、GoogleがAndroid新版「Ice Cream Sandwich」を年内に提供
http://itpro.nikkeibp.co.jp/article/NEWS/20110511/360212/?t1

Google I/O: Android 3.1をMotorola Xoomで使ってみた–3.0のブラッシュアップだな
http://jp.techcrunch.com/archives/20110510hands-on-with-android-3-1-on-the-motorola-xoom/

ポイントはOpenAccessoryToolkitと@Homeみたいです。

Google I/O: タブレットや携帯電話にいろんなデバイスをつなげるAndroid Open Accessory Toolkit
http://jp.techcrunch.com/archives/20110510google-releases-the-android-open-accessory-toolkit-for-adding-devices-to-tablets-and-phones/

GoogleがAndroid向け周辺機器を自由に開発できる「Android Open Accessory」を発表、開発キットを日本のロボット・メーカーが提供
http://itpro.nikkeibp.co.jp/article/NEWS/20110511/360216/?t1

Googleが家庭内の機器をすべてAndroidで制御するコンセプト「Android@Home」を発表
http://itpro.nikkeibp.co.jp/article/NEWS/20110511/360214/?t1

あとは、他社の後追いで、Android経由でビデオレンタルできるようになるとか、クラウド音楽配信サービスとか。

Google I/O: Androidでクラウド経由のビデオレンタル(オフラインでも視聴可)
http://jp.techcrunch.com/archives/20110510android-movie-rentals/

[Google I/O]レコード会社の承認なくGoogleが音楽サービスを立ち上げ–またまたAppleに負けそうだ
http://jp.techcrunch.com/archives/20110509without-the-labels-googles-music-locker-will-look-like-apples-ugly-sibling-again/

あと、GoogleTVも3.1ベースになるみたいで、Samsungも参入。
ということでようやくまともなラインがでてきそうです。

Google I/O: 新パートナーを見つけOSをアップデートするGoogle TV–今度はうまくいくかな?
http://jp.techcrunch.com/archives/20110510google-tv-finds-new-friends-and-an-updated-os/

2011年5月4日水曜日

iPhone SDKの教科書

今さらながらiPhoneアプリの作り方を学ぶべく導入本として購入。



内容としては、サンプルアプリを順を追って作っていくという流れで、
xcodeの使い方も含めて手順が書いてあるので
私のようなxcodeを使った開発ど素人にとっては非常に分かりやすかったです。

前半は結構よかったのですが、後半はいきなりデリゲートとかプロトコルとかでてきて
なんぞそれ状態に落ちいるので、Objective-Cについては随時調べつつやったほうがいいです。

また、現時点(2011.05)では少しばかり古い内容なので
特に私はxcode4を使ってやったのでいろいろと読み替える必要がありました。

この本を読むことで、使い方の基本については学ぶことができますが、
これをベースにどんどんアプリが作れるかというとかなり簡単なものであれば可能ですが
ちょっと違ったことをしようとするとどうするんだろうと途方にくれる気がします。

1stステップとしてはよい本だと思います。