views:

1563

answers:

5

I'm trying to find the size of an objective-c object. I'm using something similar to:

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

That just gives me the size of the pointer though.

What am I doing wrong?

A: 

I think the class description contains the size information -- it is better to look this up than querying using the sizeof operator.

dirkgently
+3  A: 

All the compiler knows about is the pointer, which is why you're getting the size of the pointer back. To see the size of the allocated object, use this:

#import <malloc/malloc.h>

// ...

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

Mike Ash has a decent write-up about some of the Obj-C runtime internals on his Q&A blog: http://mikeash.com/?page=pyblog/friday-qa-2009-03-13-intro-to-the-objective-c-runtime.html

Jason Coco
It should be noted that most classes also store their state in objects they reference via pointers. These will be allocated separately from the class (an NSString for example is a structure that contains the isa pointer, a pointer to a buffer allocated via malloc, and some other data)
rpetrich
Yes, but in this case the size of the object's structure itself doesn't change. It's the same as any structure which has a pointer as one of its members. This would also be the case for any ivars which are objects as well.
Jason Coco
A: 

The size of an (objective-c) object is not easy to find because it's not even easy to define. What did you mean with "size of an objective-c object"?

The size of the reference is the size of a pointer (as returned by sizeof(obj_ref)).

The size of the memory that was allocated on creation (+alloc) may be found by the way that Jason gave in the first answer. But this depends on the runtime. The gnu-runtime differs from the apple-runtime. Eventually this is only the memory that is needed by the primitive data types the instance consists of. But not the memory that may be allocated later on (i.e. during initialization (-init)) for objects referenced by the ivars or strings.

An instance of the class

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

needs at least 5 bytes (on many systems - int size may vary) plus static overhead if the runtime needs it. The size of such an object is obvious.

But for an instance of the class

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

the definition of the "size" ist complicated. The object needs 12 bytes (on 32bit systems) plus overhead on allocation. But maybe the name is part of the object and allocated/freed by it. Should the memory which the actual name needs be part of the object's size? And what about the referenced objects?

Tilo Prütz
Don't forget to add the 4/8 bytes to each object for the isa pointer which would be required on both runtimes.
Jason Coco
+1  A: 

In the GNU Objective-C runtime, you can use (you must import <objc/objc-api.h>:

class_get_instance_size ([MyClass class]);

On Mac OS X you can use (you might need to import <objc/runtime.h>):

class_getInstanceSize ([MyClass class]);

These functions will return how much memory is required to allocate an object, it will not include memory allocated by an object when it is initialised.

dreamlax
Just as a note, class_getInstanceSize is only available on 10.5
Jason Coco
A: 

First of all, i think its clear from the above posts that the object size is given by malloc_size(myObject), as suggested by Jason and also on the Mac OS reference manual:

"The malloc_size(ptr) function returns the size of the memory block that backs the allocation pointed to by ptr. The memory block size is always at least as large as the allocation it backs, and may be larger." (http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/malloc_size.3.html)

But if you are interested in finding out the size of the dictionary, keep in mind the following point:

The dictionary stores key-value pairs and does not contain the object itself in the value part but just increases a retain count of the object that was to be "added" and keeps a reference of that object with itself. Now, the dictionary itself just contains the references to the various objects (with a key attached). So if by any chance you are looking for the object size of all the objects refered to by the dictionary, technically that would not be the size of the dictionary. The size of the dictionary would be the sum of the size of all the keys plus the size of all the value-references against the keys plus the size of the parent NSObject. If you are still interested in finding out the size of the refered objects as well, try iterating over the dictionary values array:

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.

Hope that answers the question.

Ameer Sheikh