在NSString的isa指针上使用“setValue:forKey:”然后调用[string class]时出错

时间:2014-05-05 23:47:50

标签: objective-c nsstring objective-c-runtime

Heres是我得到的错误。

libobjc.A.dylib`_objc_trap():
0x14c13f4:  pushl  %ebp
0x14c13f5:  movl   %esp, %ebp
0x14c13f7:  ud2    

所以基本上我试图理解NSString如何工作,并试图找到一种方法来改变指向“真(char *)字符串”的指针,这被称为常量。

所以,我发现有一个名为isa的指针指向(__NSCFConstantString *)。 它让我想到,如果我改变那个指针,那么我可以改变字符串。

我试过的代码是:

NSString *st3 = [[NSString alloc] initWithString:@"hihi"];
[st3 setValue:@"change" forKey:@"isa"];

并且,结果显示

之前:

enter image description here

后:

enter image description here

似乎发生了变化,但它改变了每个具有@“hihi”字符串的NSString对象。

然后我做的是 [st3 class] 希望它会给出isa指针然后我在顶部发布了错误消息。

你能解释一下发生了什么以及为什么会这样吗? 而且,有没有办法实习(我不太确定这个术语)就像在Java中一样?

请避免说只使用“NSMutableString”我只是想弄清楚可能有某种方法可以做到这一点。

1 个答案:

答案 0 :(得分:29)

只需使用NSMutableString;可变性是它存在的原因。 ;)

NSString是不变的。不只是"包裹const char *"不变,但是,不,真的,这个东西是不可变的,存储细节对你来说是完全不透明的。

事实上,__NSCFConstantString甚至根本没有存储在堆上;没有malloc d内存,你可以捣乱。这些字符串由编译器生成,链接器将它们放在一块内存中,这些内存将在运行时读入并存储在只读内存页面上。

但是,[NSString stringWithFormat:@"%d World", 42]的结果甚至不会仅仅为字符串缓冲区存储在一块唯一分配的malloc()内存中。 很可能是(但可能不是 - 它是一个不透明的实现细节),构造格式化字符串的机制将产生一个对象,其大小将是{{1的任何私有子类的最小实例大小(请参阅类集群)是最合适的+但是需要很多字节来存储字符串数据本身。

虽然您可能会在内存中找到实际的字节并直接查找它们,但这将严重违反封装并在实际程序中完全无用。

请注意,您正在使用的NSStringisa的实例变量。它是指向实例的Class对象的指针。它不一定是恒定的,但你也不应该捣乱它。

有关NSObject的更多信息以及当您将isa实例卡入NSString广告位时,您看到特定崩溃的原因,我对这个问题的回答可能会有所帮助(也许):

objc_msgSend() dispatch table

BTW:喜欢这个问题 - 当你走上与OO编程和基金会完全不一致的道路时,对内脏进行捣乱并疯狂地破坏事物是一种极好的学习方式!不要让失败的选民得到你......好吧......如果他们应该出现,那就失败了。