Hatena::Groupiphone-dev

Ni chicha, ni limona - 平均から抜けられない僕

2009-09-30

[gcc] GCCiPhone向けにPREDEFINEDされているマクロを一覧表示する方法 17:49  [gcc] GCCでiPhone向けにPREDEFINEDされているマクロを一覧表示する方法 - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [gcc] GCCでiPhone向けにPREDEFINEDされているマクロを一覧表示する方法 - Ni chicha, ni limona - 平均から抜けられない僕  [gcc] GCCでiPhone向けにPREDEFINEDされているマクロを一覧表示する方法 - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

※同じような記事をはてなダイアリーの方でも書いています。こちらはそのiPhone版です。

これだけです。ポイントは、



です。

% echo  | /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc -arch armv6 -dM -E -x c -  | sort

参考までに、手元のiPhone 3.1 SDK(gcc 4.2)での結果を載せておきます。__VERSION__がビルド番号になるわけですが、あまり役立ちそうなものは見あたりませんでした。

#define OBJC_NEW_PROPERTIES 1
#define __APCS_32__ 1
#define __APPLE_CC__ 5575
#define __APPLE__ 1
#define __ARMEL__ 1
#define __ARM_ARCH_6K__ 1
#define __CHAR_BIT__ 8
#define __CONSTANT_CFSTRINGS__ 1
#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
#define __DBL_DIG__ 15
#define __DBL_EPSILON__ 2.2204460492503131e-16
#define __DBL_HAS_DENORM__ 1
#define __DBL_HAS_INFINITY__ 1
#define __DBL_HAS_QUIET_NAN__ 1
#define __DBL_MANT_DIG__ 53
#define __DBL_MAX_10_EXP__ 308
#define __DBL_MAX_EXP__ 1024
#define __DBL_MAX__ 1.7976931348623157e+308
#define __DBL_MIN_10_EXP__ (-307)
#define __DBL_MIN_EXP__ (-1021)
#define __DBL_MIN__ 2.2250738585072014e-308
#define __DEC128_DEN__ 0.000000000000000000000000000000001E-6143DL
#define __DEC128_EPSILON__ 1E-33DL
#define __DEC128_MANT_DIG__ 34
#define __DEC128_MAX_EXP__ 6144
#define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
#define __DEC128_MIN_EXP__ (-6143)
#define __DEC128_MIN__ 1E-6143DL
#define __DEC32_DEN__ 0.000001E-95DF
#define __DEC32_EPSILON__ 1E-6DF
#define __DEC32_MANT_DIG__ 7
#define __DEC32_MAX_EXP__ 96
#define __DEC32_MAX__ 9.999999E96DF
#define __DEC32_MIN_EXP__ (-95)
#define __DEC32_MIN__ 1E-95DF
#define __DEC64_DEN__ 0.000000000000001E-383DD
#define __DEC64_EPSILON__ 1E-15DD
#define __DEC64_MANT_DIG__ 16
#define __DEC64_MAX_EXP__ 384
#define __DEC64_MAX__ 9.999999999999999E384DD
#define __DEC64_MIN_EXP__ (-383)
#define __DEC64_MIN__ 1E-383DD
#define __DECIMAL_DIG__ 17
#define __DEC_EVAL_METHOD__ 2
#define __DYNAMIC__ 1
#define __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ 30000
#define __FINITE_MATH_ONLY__ 0
#define __FLT_DENORM_MIN__ 1.40129846e-45F
#define __FLT_DIG__ 6
#define __FLT_EPSILON__ 1.19209290e-7F
#define __FLT_EVAL_METHOD__ 0
#define __FLT_HAS_DENORM__ 1
#define __FLT_HAS_INFINITY__ 1
#define __FLT_HAS_QUIET_NAN__ 1
#define __FLT_MANT_DIG__ 24
#define __FLT_MAX_10_EXP__ 38
#define __FLT_MAX_EXP__ 128
#define __FLT_MAX__ 3.40282347e+38F
#define __FLT_MIN_10_EXP__ (-37)
#define __FLT_MIN_EXP__ (-125)
#define __FLT_MIN__ 1.17549435e-38F
#define __FLT_RADIX__ 2
#define __GNUC_GNU_INLINE__ 1
#define __GNUC_MINOR__ 2
#define __GNUC_PATCHLEVEL__ 1
#define __GNUC__ 4
#define __GXX_ABI_VERSION 1002
#define __INTMAX_MAX__ 9223372036854775807LL
#define __INTMAX_TYPE__ long long int
#define __INT_MAX__ 2147483647
#define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
#define __LDBL_DIG__ 15
#define __LDBL_EPSILON__ 2.2204460492503131e-16L
#define __LDBL_HAS_DENORM__ 1
#define __LDBL_HAS_INFINITY__ 1
#define __LDBL_HAS_QUIET_NAN__ 1
#define __LDBL_MANT_DIG__ 53
#define __LDBL_MAX_10_EXP__ 308
#define __LDBL_MAX_EXP__ 1024
#define __LDBL_MAX__ 1.7976931348623157e+308L
#define __LDBL_MIN_10_EXP__ (-307)
#define __LDBL_MIN_EXP__ (-1021)
#define __LDBL_MIN__ 2.2250738585072014e-308L
#define __LITTLE_ENDIAN__ 1
#define __LONG_LONG_MAX__ 9223372036854775807LL
#define __LONG_MAX__ 2147483647L
#define __MACH__ 1
#define __NO_INLINE__ 1
#define __PIC__ 2
#define __PTRDIFF_TYPE__ int
#define __REGISTER_PREFIX__ 
#define __SCHAR_MAX__ 127
#define __SHRT_MAX__ 32767
#define __SIZE_TYPE__ long unsigned int
#define __STDC_HOSTED__ 1
#define __STDC__ 1
#define __THUMB_INTERWORK__ 1
#define __UINTMAX_TYPE__ long long unsigned int
#define __USER_LABEL_PREFIX__ _
#define __USING_SJLJ_EXCEPTIONS__ 1
#define __VERSION__ "4.2.1 (Apple Inc.  build 5575) (dot 11)"
#define __VFP_FP__ 1
#define __WCHAR_MAX__ 2147483647
#define __WCHAR_TYPE__ int
#define __WINT_TYPE__ int
#define __arm 1
#define __arm__ 1
#define __pic__ 2
#define __strong 
#define __weak

KaborKabor2012/02/05 04:37Deadly accrutae answer. You've hit the bullseye!

rcvvrjnugcmrcvvrjnugcm2012/02/07 22:57E9siCs , [url=http://pipgllvstava.com/]pipgllvstava[/url], [link=http://pupivcbqgajb.com/]pupivcbqgajb[/link], http://hqqdpiqynkxl.com/

potmzoxbgspotmzoxbgs2012/02/11 00:01YHm1Jy <a href="http://nnwvnszgyxfd.com/">nnwvnszgyxfd</a>

2009-09-24

[iPhone][tips] UIImageで手っ取り早くアニメーションを作ってしまう方法 13:03  [iPhone][tips] UIImageで手っ取り早くアニメーションを作ってしまう方法 - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [iPhone][tips] UIImageで手っ取り早くアニメーションを作ってしまう方法 - Ni chicha, ni limona - 平均から抜けられない僕  [iPhone][tips] UIImageで手っ取り早くアニメーションを作ってしまう方法 - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

処理速度、とかレスポンスとかを無視してとりあえずアニメーションさせたい場合、UIImageを使うとお手軽です。

手順も簡単で、


  1. アニメーション用の画像をNSArrayに突っ込んでおく
  2. UIImageViewのanimationImagesプロパティ配列をセット
  3. 同ViewのanimationDurationプロパティに、各画像を表示する時間を設定
  4. 同ViewにstartAnimatingメッセージを送信

だけです。サンプルコードはこんな感じ(画像は72x72のサイズだと仮定しています):


- (void)viewDidLoad {
    [super viewDidLoad];
    NSArray *imgArray = [[NSArray alloc] initWithObjects:
                                             [UIImage imageNamed:@"1.png"],
                                             [UIImage imageNamed:@"2.png"],
                                             [UIImage imageNamed:@"3.png"],
                                             [UIImage imageNamed:@"4.png"],
                                             [UIImage imageNamed:@"4.png"], // 同じ画像を2回用意することでアニメーション間隔を一部変更
                                             [UIImage imageNamed:@"5.png"],
                                             nil];
    UIImageView *animationView = [[UIImageView alloc] initWithFrame:CGRectMake(124,204,72,72)];
    animationView.animationImages = imgArray;
    animationView.animationDuration = 3.0f; // アニメーション全体で3秒(=各間隔は0.5秒)
    [self.view addSubView:animationView];
    [animationView startAnimating]; // アニメーション開始!!
    [animationView release];  // きちんと後片付け
    [imgArray release]; // きちんと後片付け
}

簡単ですね。ちなみに上記ソースのように、同じ画像を再利用することでアニメーションの「待ち」を入れることも出来ます。使いようによっては色々とつぶしが利くのではないかと思います。


なお、animationDurationプロパティデフォルト値は1/30秒ですが、経験から言って10fps程度も出れば良い感じです(iPod touch 1Gにて体感上の値)。ですので、冒頭に伝えたとおりあまりシビアな時間制限が要求されるところに使うべきでは無いので悪しからず。


まとめ


参考書

この記事はErica女史の本「iPhoneデベロッパーズクックブック*1の、「8-2 レシピ:ボタンへのアニメーション要素の追加」を参考にしました。この本は発売からだいぶ時間が経っているものの、まだまだ現役で使っています。iPhoneで出来ることを一通り覚えるまでは読みづらいかもしれませんが、それを乗り越えた後は役立つレシピばかりだということに気づく、何と言うべきかスルメのような良本です。参考にしたセクションの次ではボタンを押したときにアニメーションをさせたいときはどうしたら良いか、が書かれていますし。


日本発のiPhone開発本ではまだスルメのような本は少ないだけに、1冊持っておいて損はないと思います。

*1Amazonインスタントストアへのリンクです。

2009-09-17

[Tips] CGRect構造体の簡単なログ出力方法 13:06  [Tips] CGRect構造体の簡単なログ出力方法 - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [Tips] CGRect構造体の簡単なログ出力方法 - Ni chicha, ni limona - 平均から抜けられない僕  [Tips] CGRect構造体の簡単なログ出力方法 - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

iPhone SDKに限らないのですが、CGRect構造体は簡単に内容を表示できます。


NSLog(@"view frame = %@\n", NSStringFromCGRect(self.view.frame));

これを実行すると、


2009-09-16 23:03:59.001 XXX[1574:20b] view frame = {{0, 0}, {320, 387}}

みたいに表示されます。いちいちoriginとかheightとかを個別指定しなくてもいいので便利。

kouichikouichi2009/09/25 12:50これは知らなかった!これからのデバッグでちょっとだけ楽ができる。

paellapaella2009/09/25 20:30ありがとうございます。また何か良いTipsがあったら書きますね。

zerozero2009/10/03 05:10NSStringFromCGRectとNSStringFromCGPointをこちらで知りました。
おかげで一週間ほど悩んでいた座標関係の処理が解決しました。
ありがとうございました。

paellapaella2009/10/05 19:20いいえ、お礼なんてとんでもないです。
こんな僅かばかりの情報で問題を解決してしまうことの方がすごいですよ。

2009-09-09

[iPhone][books] オライリーiPhone SDKアプリケーション開発ガイドを買ったらすごく良かった 16:49  [iPhone][books] オライリーのiPhone SDKアプリケーション開発ガイドを買ったらすごく良かった - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [iPhone][books] オライリーのiPhone SDKアプリケーション開発ガイドを買ったらすごく良かった - Ni chicha, ni limona - 平均から抜けられない僕  [iPhone][books] オライリーのiPhone SDKアプリケーション開発ガイドを買ったらすごく良かった - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

以前の日記「 [iPhone][Develop] オライリーからiPhoneSDK開発にヨサゲな本が出るみたい→出た。すごく良かった - Ni chicha, ni limona - 平均から抜けられない僕 - iPhoneアプリ開発グループ」で記していた書籍:


 iPhone SDK アプリケーション開発ガイド*1

   By Jonathan Zdziarski


を購入しました。これ、すごく良かったです。


  • オーディオ周りの解説は過去に例を見ないほどの充実ぶり
    • Mac OS XでのCore Audioを使った開発にも流用できる内容
  • CFNetworkがサンプルアプリ付きで説明されている
    • これまではHTTP系くらいしか無かったので、結構貴重な情報です。*2

などなど。これまでのiPhoneアプリ本では載っていない情報がサンプルプログラム付きで紹介されていて、とても参考になっています。


オライリー本の習慣として図や画面写真が少ないという欠点はあるものの(なので全くの初心者には勧められないです)、そのぶん密度が濃かったです。

お世辞抜きでオススメです。


ちなみにこの本、まえがきを読むと原著者であるJonathan Zdziarski氏のぼやきから始まっていて、思わず笑ってしまいました。

買った人は、まずはまえがきから読むことをオススメします。色んな意味で必読です。w

*1Amazonインスタントストアへのリンクです

*2POSIXソケットの概念を理解していることが必要ですが

2009-09-07

[iPhone][Mac][develop] objc_msgSend()で落ちているときにどうすればいいか 18:56  [iPhone][Mac][develop] objc_msgSend()で落ちているときにどうすればいいか - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [iPhone][Mac][develop] objc_msgSend()で落ちているときにどうすればいいか - Ni chicha, ni limona - 平均から抜けられない僕  [iPhone][Mac][develop] objc_msgSend()で落ちているときにどうすればいいか - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

※以下の内容は「Hamster Emporium: [objc explain]: So you crashed in objc_msgSend()」で記されていた文章を和訳(意訳)したものです。


Macで開発していると、スタックトレースの底がobjc_msgSend()になって落ちる不具合に悩まされることがあります。

そんなときの、問題解決の一助になれば幸いです。


Special Thanks

翻訳の際、Twitter@ewa4618さんと@nakimoさんに的確なアドバイスをいただきました。この場を借りてお礼を申し上げます。ありがとうございます。


■「objc_msgSend()で落ちた。一体どうしたの?」

実は、大抵の場合で解放済みのオブジェクトにメッセージを送ってしまったか、もしくはポインタは正しくてもその先がぶっ壊れているか(対象がバッファオーバーランの被害に遭っていたり、ダングリングポインタになっていたり)のどちらかなんだ。

まあ、ときにはランタイムの持つデータ構造にうっかり触ってしまってエラーなんてこともあるけれどもね。

でも実際はレシーバオブジェクト自身に問題があることがほとんどだ。


だからデバッガかクラッシュログを駆使すれば、バックトレースなんかよりずっと的確な情報が得られるよ。

さあ、始めてみよう。


■レシーバとセレクタが使うレジスタ

objc_msgSend()には、プログラムが落ちたときに実際にCPU内(のレジスタ)で使われていた「レシーバオブジェクト」と「セレクタ」のアドレスが格納されているんだ。

この値は問題を分析するのにすごく役立ってくれる。


ただ、このレジスタCPUアーキテクチャ毎に違う名前(変数)が使われているから、それぞれにあったものを見ないといけない。

だからまずは次の表を見て、自分の環境では何を調べたら良いかを覚えておいてほしい。

あ、これたぶんSnow Leopardでも同じだと思う。


 objc_msgSend
objc_msgSend_fpret
objc_msgSend_stret
 レシーバ/セレクタレシーバ/セレクタ
i386eax* / ecxeax* / ecx
x86_64rdi / rsirsi / rdx
ppcr3 / r4r4 / r5
ppc64r3 / r4r4 / r5
arm(iPhone!!)r0 / r1r1 / r2

(*i386補足: ほとんどはeaxがレシーバだけれど、残念ながらそうじゃないときもある。もし落ちる直前のobjc_msgSend()の中身を調べられたら、eaxは別の値になっていると思うけど)


■レシーバーと不正なアドレスを突き止める

レシーバのアドレスと不正なアドレスが分かれば、クラッシュの原因となった問題への幾らかのヒントが得られるんだ。


クラッシュログを覗いてみると、落ちたスレッドが使っていたレジスタテーブル(上表と見比べてね)の中にレシーバーのアドレスが残っている。そして不正だったアドレスそのものが最上段に記されているはずだ(たとえば「KERN_PROTECTION_FAILURE at <invalid address>」みたいに)。


デバッガコンソールだと不正アドレスはgdbプロンプトの直前にある。レジスタ値にはprint命令とレジスタ名称とでアクセスできる。これは便利だね。

    Program received signal EXC_BAD_ACCESS, Could not access memory.
    Reason: KERN_PROTECTION_FAILURE at address: 0x00000001
    0x00090ec4 in objc_msgSend ()
    (gdb) p/x $eax
    $1 = 0x1

ちなみに上の例でのソースは[(id)1 release]だったんだけど、実際に落ちたときはもっと興味深い情報が得られるんだよ。


たいてい1-2つの事象が起きるんだ。たとえばレシーバのアドレスは嘘っぱちの値で不正アドレスはレシーバのアドレスと同じ(か、16/32バイトずれている)だったり、レシーバのアドレスはそれっぽくても不正アドレスがレシーバのisaポインタだったり。

後者の場合、既にdeallocされたオブジェクトを使っていたり、別の誰かが(本当は正しい)オブジェクトをぶっ壊してくれていたりすることがほとんどだよ。


さあ、クラッシュの残骸から下に挙げたような特別な値を探し出そう。そしてそれに近いアドレスも。アーキテクチャによっては、isaのアドレスが不正なときに16か32バイトオフセットしたところで落ちるものもあるからね。


16で割り切れない値 - アラインメントエラー
malloc()は16バイトで割り切れるブロックを必ず返す。だからレシーバのアドレスが16で割り切れない場合、まだ一度も正しいオブジェクトをポイントしたことがないわけだね。
上位と下位の2bitがすべて1になっている - free済み
malloc()で確保されたブロックが解放された場合、アロケータはそのアドレスにfree list pointerを書くことがある。つまり、もし解法済みオブジェクトを使用していた場合には上位/下位の2bit(合計4bit)が全て1になっているはずだよ。
全ビットが反転している - GC済み
上のfree listのケースと同様、ガーベージコレクションの対象になったオブジェクト(ブロック)は全ビットが反転している。この場合、一見意味不明なアドレスになっていても~を使ってみるとソレっぽいアドレスになっている。
0xa1b1c1d3 - CFコンテナ
CoreFoundationのコンテナは、削除済み/未使用のアイテムにこのマジックナンバーを使うんだ。きっと解放済みのオブジェクトがコンテナとして再利用されたか、オブジェクトとして再利用されている解放済みのコンテナを使ったか、それともマルチスレッドのルールを守らずに共有しているコンテナからポインタを呼んでしまったか、どれかだと思う。
ASCII text
きっと解放されたオブジェクト文字列として再利用されている。もしくは誰かが使って解放した文字列領域を再利用した直後か、それとも文字列バッファオーバーランを起こしているか。そんなときはgdbのasciifyコマンドを使って情報を表示してみよう。以下はURLに関係する何かが書き込まれてしまったときの出力例だよ。

% asciify 0x2e777777
###.www###
###www.###

セレクタを突き止めよう

コンパイラ最適化ってやつは、バックトレースの底から2つ目のフレーム情報(objc_msgSend()のすぐ上)を、実際に落ちた場所とは異なる場所にしてしまうことがあるんだ。メッセージ呼び出しに成功したとき、そのメソッドはクラッシュしたところで末尾呼出(callではなくjmp)を作ってしまうから。

この最適化のせいでバックトレース途中のフレームからは必要な情報が抜け落ちてしまう。だからセレクタを示すレジスタを調べて、本当に落ちた場所を突き止めるんだよ。


セレクタはユニークなC文字列へのポインタだ(将来のバージョンでは変わるかもしれないけど)。これってデバッグにすごく便利だよね?

クラッシュしたらデバッガコンソールを開いて下のコマンドを入力してみよう。もちろん、レジスタは適宜読み替えてね。


    (gdb) x/s $ecx
    0xa1029: "release"

ちなみにSnow Leopardのクラッシュレポーターではログにセレクタ名を書いてくれるようになったんだって。

Application Specific Information:

objc_msgSend() selector name: release

ただ、上の方法でうまくいかなかった場合(やSnow Leopardを持っていない場合)、セレクタ名をクラッシュログから調べるのは結構骨の折れる作業になってしまうのを覚悟してほしい。さらには報われないこともある。

以下に方法を書いておくから試してみてくれ*1


1. 落ちたスレッドのクラッシュログから、セレクタのアドレスが書かれたレジスタを見つける。

    ecx: 0x000a1029

2. クラッシュログのバイナリイメージから、セレクタのアドレスが範囲内に含まれているライブラリ(バイナリ)を探す。この範囲、大抵はアプリケーション自身かlibobjc.A.dylibのどちらかだと思う。もし範囲外だったら、残念、ギブアップだ。

    0x8b000 -   0x106ff7  libobjc.A.dylib ??? (???) <9b5973b7fa88f9aab7885530c7b278dd> /usr/lib/libobjc.A.dylib

3. クラッシュログのアドレスとマッチするイメージのコピーを探す。探すときにはUUIDを使うのが定石だ。

    % dwarfdump -u /usr/lib/libobjc.A.dylib
    UUID: 26650299-C6EA-B1C8-52D6-072AC874D400 (ppc) /usr/lib/libobjc.A.dylib
    UUID: 9B5973B7-FA88-F9AA-B788-5530C7B278DD (i386) /usr/lib/libobjc.A.dylib
    UUID: D2A4E8E1-3C1C-E0D9-2249-125B6DD621F8 (x86_64) /usr/lib/libobjc.A.dylib

今回はi386向けのlibobjc.A.dylibが対象だと分かるね。

この例のようにシステムライブラリだった場合、同じバージョンのOSが使うライブラリを用意してほしい。逆にアプリケーションでも、クラッシュしたのと同じバイナリを用意する必要がある。そりゃそうだよね?


4. セレクタオフセットを計算する。この例ではlibobjc.A.dylibが0x8b000から始まっていたから、その値を引いてあげるんだ。

    0xa1029 - 0x8b000 = 0x16029

5. Cストリングをイメージから引っ張り出す。下のコマンドを使うときは、アーキテクチャに気をつけてほしい

    % otool -v -arch i386 -s __TEXT __cstring /usr/lib/libobjc.A.dylib | grep 16029
    00016029  release

以上です。間違っている箇所や、意味不明なところがあったら指摘してもらえると嬉しいです。

*1:訳者注:この方法はObjective-Cに限らずCやC++でもよく行われる方法です。

2009-09-04

[iPhone] UIBarButtonSystemItem系の画像 18:23  [iPhone] UIBarButtonSystemItem系の画像 - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [iPhone] UIBarButtonSystemItem系の画像 - Ni chicha, ni limona - 平均から抜けられない僕  [iPhone] UIBarButtonSystemItem系の画像 - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

マクロ名と画像の関係をよく忘れてしまうので参照先をメモ。


  Page Not Found - Apple Developer


に載ってます。どう使えば良いのかも記されているので、Rejectされないように覚えておかないと。

MatthewMatthew2012/08/08 17:49That's way the bestest aenswr so far!

bnvmkpbnvmkp2012/08/09 20:093nSlJH , [url=http://ylfidzerkosd.com/]ylfidzerkosd[/url], [link=http://mqlpqfqgcbsi.com/]mqlpqfqgcbsi[/link], http://drqfjekifipw.com/