【问题标题】:Checking the size of an object in Objective-C在 Objective-C 中检查对象的大小
【发布时间】:2010-10-20 04:54:10
【问题描述】:

我正在尝试查找objective-c 对象的大小。我正在使用类似于:

    NSLog(@"sizeof myObject: %ld", sizeof(*myObject));

这只是给了我指针的大小。

我做错了什么?

【问题讨论】:

  • myObject 的类型是什么?
  • 在这种情况下,它是一个 NSDictionary,具有任意数量的键和值。
  • 很可能是因为 NSDictionary 确实是一个复杂数据结构的不透明句柄。查找您的标题(我手边没有 Mac,很抱歉)。
  • 这是因为对象基本上只是一个结构,其中包含指向对象的类结构的指针,仅此而已。运行时实际上为一个对象分配内存并布置其内部数据。

标签: c objective-c sizeof


【解决方案1】:

编译器只知道指针,这就是为什么要返回指针的大小。要查看分配对象的大小,请使用以下代码之一 sn-ps:

使用 ARC:

#import <malloc/malloc.h>

// ...

NSLog(@"Size of %@: %zd", NSStringFromClass([myObject class]), malloc_size((__bridge const void *) myObject));

没有 ARC:

#import <malloc/malloc.h>

// ...

NSLog(@"size of myObject: %zd", malloc_size(myObject));

Mike Ash 在他的问答博客上写了一篇关于 Obj-C 运行时内部的文​​章:http://mikeash.com/?page=pyblog/friday-qa-2009-03-13-intro-to-the-objective-c-runtime.html

【讨论】:

  • 应该注意的是,大多数类也将它们的状态存储在它们通过指针引用的对象中。这些将与类分开分配(例如,NSString 是一个包含 isa 指针、指向通过 malloc 分配的缓冲区的指针以及其他一些数据的结构)
  • 是的,但在这种情况下,对象结构本身的大小不会改变。它与任何将指针作为其成员之一的结构相同。这也适用于任何作为对象的 ivars。
  • 即使在类扩展可以声明实例变量的最新运行时(假设可以在运行时从包中加载类扩展),这是否仍会返回正确的大小?
  • 如果您使用 ARC,请改用此代码(但不要忘记导入 malloc.h!):NSLog(@"Size of %@: %zd", NSStringFromClass([myObject class]), malloc_size((__bridge const void *) myObject));
【解决方案2】:

我建议使用class_getInstanceSizemalloc_good_size 来查看结果。这不会在返回的大小中显示 ivars 和其他内容。

#import <malloc/malloc.h>
#import <objc/runtime.h>

NSLog(@"Object Size: %zd", malloc_good_size(class_getInstanceSize([yourObject class])));

【讨论】:

    【解决方案3】:

    首先,我认为从上述帖子中可以清楚地看出,object 大小由 malloc_size(myObject) 给出,正如 Jason 和 Mac OS 参考手册所建议的那样:

    "malloc_size(ptr) 函数返回支持所指向的分配的内存块的大小 指针。内存块大小始终至少与其支持的分配一样大,并且可能更大。” (http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/malloc_size.3.html)

    但如果您有兴趣找出字典的大小,请记住以下几点:

    字典存储键值对并且在值部分包含对象本身,而只是增加要“添加”的对象的保留计数并保留该对象的引用对象与自身。现在,字典本身只包含对各种对象的引用(带有一个键)。因此,如果您有机会查找字典引用的所有对象的对象大小,从技术上讲,这不会是字典的大小。字典的大小将是所有键的大小加上所有对键的值引用的大小加上父 NSObject 的大小的总和。如果您仍然对找出引用对象的大小感兴趣,请尝试遍历字典值数组:

    NSArray *myArray = [myDictionary allValues];
    id obj = nil;
    int totalSize = 0;
    for(obj in myArray)
    {
        totalSize += malloc_size(obj);
    }
    //totalSize now contains the total object size of the refered objects in the dictionary.
    

    希望能回答这个问题。

    【讨论】:

    • 钥匙怎么样?实际上 NSDictionary 使用 NSCopying 协议实现其密钥。
    【解决方案4】:

    在 GNU Objective-C 运行时中,可以使用(必须导入&lt;objc/objc-api.h&gt;:

    class_get_instance_size ([MyClass class]);
    

    在 Mac OS X 上您可以使用(您可能需要导入 &lt;objc/runtime.h&gt;):

    class_getInstanceSize ([MyClass class]);
    

    这些函数将返回分配一个对象需要多少内存,它不包括一个对象在初始化时分配的内存。

    【讨论】:

    • 请注意,class_getInstanceSize 仅在 10.5 上可用
    【解决方案5】:

    (objective-c)对象的大小不容易找到,因为它甚至不容易定义。 “objective-c 对象的大小”是什么意思?

    引用的大小是指针的大小(由 sizeof(obj_ref) 返回)。

    创建时分配的内存大小(+alloc)可以通过Jason在第一个答案中给出的方式找到。但这取决于运行时。 gnu-runtime 与 apple-runtime 不同。最终,这只是实例所包含的原始数据类型所需的内存。但 不是 稍后可能为 ivars 或字符串引用的对象分配的内存(即在初始化 (-init) 期间)。

    类的一个实例

    @interface FirstClass
    {
        int _someInt;
        char _someChar;
    }
    …
    @end
    

    需要至少 5 个字节(在许多系统上 - int 大小可能会有所不同)加上运行时需要的静态开销。这样一个物体的大小是显而易见的。

    但是对于类的一个实例

    @interface SecondClass
    {
        FirstClass *_someObject;
        char *_name;
        id _data;
    }
    …
    @end
    

    “大小”的定义很复杂。该对象需要 12 个字节(在 32 位系统上)加上分配开销。但也许名称是对象的一部分并由它分配/释放。实际名称所需的内存是否应该是对象大小的一部分?那么引用的对象呢?

    【讨论】:

    • 不要忘记为每个对象添加 4/8 字节的 isa 指针,这在两个运行时都需要。
    【解决方案6】:

    我认为类描述包含大小信息——查找它比使用sizeof 运算符查询要好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-14
      • 1970-01-01
      • 2011-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-27
      相关资源
      最近更新 更多