"NSString stringWithUTF8String:" 过于敏感

3
我正在使用高级Cocoa功能进行字符串操作,例如NSStringNSData,而不是深入到C级别的东西,例如处理char数组。
有时候,+[NSString stringWithUTF8String:]会返回nil,即使最初使用-[NSString UTF8String]创建的字符串完全正常。人们会认为这种情况发生在输入格式错误时。以下是一个失败的示例输入(十六进制):
55 6B 66 51 35 59 4A 5C 6A 60 40 33 5F 45 58 60 9D 47 3F 6E 5E 
60 59 34 58 68 41 4B 61 4E 3F 41 46 00

和ASCII:

UkfQ5YJ\j`@3_EX`G?n^`Y4XhAKaN?AF

这是一个随机生成的字符串,用于测试我的子程序。

char * buffer = [randomNSString UTF8String];
// .... doing things .... in the end, buffer is the same as before
NSString * result = [NSString stringWithUTF8String:buffer];
// yields nil

编辑:以防有人没有理解隐含的问题,在-v模式下,问题如下:

为什么[NSString stringWithUTF8String:]有时会在一个完全形式的UTF8字符串上返回nil


-UTF8String-stringWithUTF8String:之间,自动释放池是否有可能被清空? - user557219
@Bavarious:不,当调用stringWithUTF8String:时,buffer仍然是存在且有效的。 - Joe Völker
1
你能发布产生该缓冲区的原始UTF-8字符串吗?也许先通过“-dataUsingEncoding:”提供一个NSData表示,然后再使用“-UTF8String”获取缓冲区。 - user557219
1
给定的ASCII和十六进制表示之间存在不匹配 -- ASCII中不存在9D。 - walkytalky
1
查看UTF8规范,这个缓冲区不是有效的UTF8,所以NSString失败了。所以我想问题是为什么它不正确?如果你去掉中间人,只需使用result=[NSString stringWithUTF8String:[randomNSString UTF8String]],你会得到一个有效的结果吗? - walkytalky
randomNSString 是如何创建的? - Peter Hosey
2个回答

2

walkytalky是正确的。在这种方式下,9d不符合UTF8的规范。UTF8字节中,前导位为10的字节被保留作为连续字符,它们永远不会出现在没有具有多个前导位的前缀字符的情况下。


0

这有点冒险,因为我们没有足够的信息来正确诊断问题。

例如,如果在您分配result内存的时候,randomNSString不再存在,例如在引用计数环境中已被释放或在GC环境中被回收,则可能buffer指向已经被释放但尚未重用的内存(这解释了为什么它仍然是相同的)。

但是,创建新的NSString需要分配内存,它可能使用由buffer指向的块,这意味着您的UTF8字符串将被新NSString的内部删除。您可以通过在失败创建result之后记录 buffer 的内容来测试此理论。不要使用%s指定符号,而应打印十六进制字节。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接