NSString 文字放在内存中的什么位置?

where is NSString literal placed in memory?

我对 NSString 进行了测试。

int a = 10;
NSString *str1 = @"str";
NSString *str2 = [NSString stringWithFormat:@"str"];
NSString *str3 = @"str";
NSString *str4 = @"str2";
NSLog(@"%p %p | 3 %p | 4 %p | a %p", str1,str2,str3,str4,&a);

结果是

0x1286287c8 0xa000000007274733 | 3 0x1286287c8 | 4 0x1286287e8 | a 0x7ffeeb215b14

此测试放置在 iPhone 6s(11.1) 模拟器中。那么 str1 在内存中的位置是什么?是堆栈还是堆?

请注意,您好奇的值 0xa000000007274733odd - 这是设置的最低有效位。对象指针通常是偶数 - 查看您显示的其他指针。

奇值指针表明它可能是 Apple 的 标记指针之一,其中数据不是分配对象,而是直接存储在指针本身中。

r 的 Unicode 是 0x72,后面是 st。所以看起来你有里面字符的 Unicode。

Mike Ash 在 2015 年对标记的字符串进行了 good article,尽管您的值似乎与他发现的方案不符。但是,我认为这是某种带标记的指针。

HTH

附录

我看到您编辑了问题以询问文字是在堆栈中还是堆中,这让我意识到您在询问 str1,哎呀。文字将在 "data segment" 中,与代码位于同一内存区域。

要查看此内容,请尝试分配一个通用对象(NSObject 可以,但不是 NSString,后者往往会得到特殊处理)以查看堆对象的去向,并获取地址C 函数以查看代码的去向。您可能会发现 str1 最接近后者。

So what's the place of str1 in memory? is it Stack or Heap?

字符串 -- Objective-C 对象 -- 永远不能在堆栈上 *。从未支持基于堆栈的 ObjC 对象。

不过,Objective-C 对象可以位于三个位置之一。好吧,两个,真的,第三个很奇怪。

  1. 对象可以在堆上。实际上,它位于 malloc()d(虽然并不总是 malloc(),但这是一个实现细节)和前 4(32 位)或 8(64 位)字节的内存块中将是指向对象 class 的指针,并且可能是编码到所述指针中的一些元数据(即不要只是抓住 isa 并认为你有一个有效的 class ).

  2. 一个对象可能在dyld映射到内存的只读内存中。这些对象实际上是由链接器创建的,是可执行文件的一部分。 NSString 常量属于这一类。 NSArray 和 NSDictionary 常量没有;它们仍然按照上面的 (1) 动态分配。注意一个奇怪的地方;因为它们未分配,所以它们不遵循 (1) 的字符串 16 字节(通常)对齐分配模式。事实上,它们可能是 2 字节对齐的(它们不太可能是奇数,但这是另一个可能会改变的实现细节)。

  3. 它们可能是标记指针。如果设置了最低位——一个奇数地址——这意味着 "tagged pointer"。但是,这也是一个可以——并且已经——改变的实现细节。使用标记指针,根本没有分配。 "pointer" 根本不是指针。指针就是数据;对于 NSNumber,包含的数字的值和类型在对象 "pointer".

  4. 中编码

  • 唯一的例外是块。它们可以在堆中,在可执行文件加载的内存映射数据段中,或者在栈上.

但是,这是另一个实现细节。只是,在这种情况下,您会接触到它。虽然此时 ARC 下的编译器实际上使其在很大程度上完全自动化,但在某些情况下,您仍然需要复制一个块以确保它在声明范围消失之前移动到堆中。

但是,由于块的 class 没有暴露,也没有任何手动分配块的方法,我将坚持 Objective-C 对象永远不会在堆栈上。 ;)