【问题标题】:Error when using "setValue: forKey:" on an NSString's isa pointer then calling [string class]在 NSString 的 isa 指针上使用“setValue:forKey:”然后调用 [string class] 时出错
【发布时间】:2014-06-22 10:03:51
【问题描述】:

这就是我对错误的看法。

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"];

而且,结果显示

之前:

之后:

它似乎改变了,但它改变了每个具有 @"hihi" 字符串的 NSString 对象。

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

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

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

【问题讨论】:

  • 哦不,请不要在不知道你在做什么的情况下玩isa。如果您想了解如何更改对象类别,请使用object_setClass
  • 即使你改变了类,对象的内部布局也不会匹配新类所期望的。因此,您很可能只会导致崩溃。即使您认为它们应该是独立的副本,也可以共享不可变字符串。因此,您将无法可靠地将更改限制为单个实例。最后,您更改了一个对象的类,但不是将其更改为不同的类,而是将其更改为字符串?!? @"changed" 不是一个类,所以它不适合 isa 指针(即使修改它是明智的)。
  • cStringUsingEncoding: 实际上可能会给你一个指向 NSString 中的 const char* 缓冲区的指针,但没有理由这样做。如果确实如此,并且您更改了该内存位置的数据,则编译器没有理由必须在您期望的代码中使用该数据。

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


【解决方案1】:

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

NSString 是常量。不仅仅是“包装一个const char *”常量,而是“不,真的,这个东西是不可变的,存储细节对你来说完全不透明”。

事实上,__NSCFConstantString 甚至根本没有存储在堆上;不会有mallocd 内存块可供您使用。此类字符串由编译器生成,链接器将它们放置在一块内存中,该块将在运行时读取并存储在只读内存页上。

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

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

请注意,您正在使用的isaNSObject 的实例变量。它是一个指向实例的 Class 对象的指针。它不一定是恒定的,但你也不应该对此感到厌烦。

有关isa 的更多信息以及为什么当您将NSString 实例插入isa 插槽时会看到特定的崩溃,我对这个问题的回答可能会有所帮助(也许):

objc_msgSend() dispatch table

顺便说一句:喜欢这个问题——当你走在一条与 OO 编程和 Foundation 完全不一致的道路上时,搞砸内部和疯狂地破坏事物是一种很棒的学习方式!不要让失望的选民让你……好吧……失望,如果他们应该出现的话。

【讨论】:

  • 您的意思是说“isa ... 不是实例变量”吗?
  • @KenThomases 不,isaNSObject 类声明的唯一实例变量。
  • @bbum 谢谢先生的最后一句话,这对我很有帮助,让我振作起来。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-27
  • 1970-01-01
  • 1970-01-01
  • 2014-05-19
  • 1970-01-01
相关资源
最近更新 更多