我在vanilla 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] ⊢ ⊣ ⊥ ⊻ ⊼ ⊂ ⊃ ⊑ ⊒
八进制几乎总是在同一个角色上发生,并且打嗝每次运行随机发生约3次。
虽然它在NSLog()中相对无害,但它暗示unicode字符可能在某种程度上不规则地处理。如果有这种行为或某些资源的历史,我可以看到这将是伟大的。
[附录:删除了我如何遇到此问题的参考。理解为什么以及如何NSLog获取unicode字符的损坏读取是我的希望。]
答案 0 :(得分: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“没有看到”那个 第一次读取的最后一个字节和第二次读取的前两个字节是部分的 相同的UTF-8序列。我假设Xcode将所有3个字节视为无效的UTF-8序列 并将它们打印为八进制数字。
答案 1 :(得分:0)
一个解决方法,在你的循环中,放一个“fflush(stderr);”在第二次NSLog声明之后;这将强制stderr在继续之前提交并写入缓冲区。