11

バニラiPadシングルビューアプリのviewDidLoad関数で次のコードを実行しています。

/*
 *  Print the string.  A lot.
 */
for (int i = 0; i < 300; i++) {
    NSLog(@"%d\n", i);
    NSLog(@"⊢ ⊣ ⊥ ⊻ ⊼ ⊂ ⊃ ⊑ ⊒ \n");
}

出力は次のようになります。

2013-02-04 20:17:49.718 testplay[59585:c07] 228
2013-02-04 20:17:49.718 testplay[59585:c07] ⊢ ⊣ ⊥ ⊻ ⊼ ⊂ ⊃ ⊑ ⊒ 
2013-02-04 20:17:49.719 testplay[59585:c07] 229
2013-02-04 20:17:49.719 testplay[59585:c07] ⊢ ⊣ ⊥ ⊻ ⊼ ⊂ ⊃ ⊑ ⊒ 
2013-02-04 20:17:49.719 testplay[59585:c07] 230
2013-02-04 20:17:49.720 testplay[59585:c07] ⊢ ⊣ ⊥ ⊻ ⊼ ⊂ ⊃ ⊑ ⊒ 
2013-02-04 20:17:49.720 testplay[59585:c07] 231
2013-02-04 20:17:49.720 testplay[59585:c07] ⊢ ⊣ ⊥ ⊻ ⊼ ⊂ ⊃ \342\212\221 ⊒ 
2013-02-04 20:17:49.723 testplay[59585:c07] 232
2013-02-04 20:17:49.724 testplay[59585:c07] ⊢ ⊣ ⊥ ⊻ ⊼ ⊂ ⊃ ⊑ ⊒ 

8進数はほとんどの場合同じキャラクターで発生し、しゃっくりは1回の実行で約3回ランダムに発生します。

NSLog()では比較的無害ですが、Unicode文字が特定のレベルで不規則に処理される可能性があることを意味します。この振る舞いの歴史や私が見ているかもしれないリソースがあれば、それは素晴らしいことです。

[補遺:この問題に遭遇した方法への参照を削除しました。NSLogがUnicode文字の破損した読み取りを取得する理由と方法を理解することが、ここでの私の希望です。]

4

2 に答える 2

8

短縮版:

NSLog()これは、出力のUTF-8シーケンスが、デバッグされたプロセスの標準エラーにXcodeが使用する疑似端末のバッファーの境界にある場合に発生すると思います。

私の仮定が正しければ、これはXcodeデバッガー出力の問題であり、アプリケーションでのUnicodeの問題を意味するものではありません。

ロングバージョン:

シミュレーターでアプリを実行するlsof -p <pid_of_simulated_app>と、標準エラー(ファイル記述子2)が疑似端末にリダイレクトされることが示されます。

# lsof -p 3251
...
testplay 3251 martin    2w     CHR               16,2     0t131     905 /dev/ttys002
...

そしてlsof -p <pid_of_Xcode>、Xcodeが同じ疑似端末を開いていることを示しています。

# lsof -p 3202
...
Xcode   3202 martin   51u     CHR               16,2       0t0     905 /dev/ttys002
...

NSLog()標準エラーに書き込みます。システムコールトレーサー「dtruss」を使用すると、Xcodeが疑似端末からログメッセージを読み取ることがわかります。単一のログメッセージの場合

NSLog(@"⊢ ⊣ ⊥ ⊻ ⊼ ⊂ ⊃ ⊑ ⊒ \n");

次のようになります。

# dtruss -n Xcode -t read_nocancel
 3202/0xe101:  read_nocancel(0x31, "2013-02-05 08:57:44.744 testplay[3251:11303] \342\212\242 \342\212\243 ... \342\212\222 \n\0", 0x8000)       = 82 0

しかし、NSLog()互いに急速に続く多くのステートメントでは、次のことが発生する場合があります。

# dtruss -n Xcode -t read_nocancel
...
 3202/0xd828:  read_nocancel(0x33, "2013-02-05 08:39:51.156 ...", 0x8000) = 1024 0
 3202/0xd87b:  read_nocancel(0x33, "\212\273 \342\212\274 ...", 0x8000) = 24 0

ご覧のとおり、Xcodeは疑似端末から1024バイトを読み取り、次の読み取りは不完全なUTF-8シーケンスで始まります。この場合、Xcodeは、最初の読み取りの最後のバイトと2番目の読み取りの最初の2バイトが同じUTF-8シーケンスの一部であることを「認識しません」。Xcodeは3バイトすべてを無効なUTF-8シーケンスとして扱い、8進数として出力すると思います。

于 2013-02-05T08:21:45.640 に答える
0

回避策として、ループに「fflush(stderr);」を配置します。2番目のNSLogステートメントの後。これにより、続行する前にstderrが強制的にバッファをコミットして書き込みます。

于 2013-02-07T00:58:28.343 に答える