where is NSString literal placed in memory? - ios

I made a test for 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);
result is
0x1286287c8 0xa000000007274733 | 3 0x1286287c8 | 4 0x1286287e8 | a 0x7ffeeb215b14
this test placed in iPhone 6s(11.1) Simulator. So what's the place of str1 in memory? is it Stack or Heap?

Note that your curious value, 0xa000000007274733, is odd - that is the least significant bit is set. Object pointers are usually even - see the other ones you've displayed.
An odd-valued pointer is an indicator that it might be one of Apple's tagged pointers, where instead of allocating an object the data is stored directly in the pointer itself.
The Unicode for r is 0x72, s & t follow. So it looks like you have the Unicode for the characters in there.
Mike Ash did a good article on tagged strings back in 2015, though your value doesn't seem to match the scheme he discovered. However I'd go with this being a tagged pointer of some kind.
HTH
Addendum
I see you edited the question to ask whether the literal is in the stack or heap, and that made be realise you were asking about str1, oops. The literal will be in a "data segment", in the same area of memory as the code.
To see this try allocating a general object (an NSObject will do, but not an NSString which tend to get special treatment) to see where a heap object goes, and taking the address of a C function to see where the code goes. You'll probably find str1 is closest to the latter.

So what's the place of str1 in memory? is it Stack or Heap?
A string -- an Objective-C object -- can never be on the stack *. Stack based ObjC objects have never been supported.
An Objective-C object can be in one of three places, though. Well, two, really, and the third is weird.
An object can be on the heap. It is, effectively, in a hunk of memory that was malloc()d (though not always malloc(), but that is an implementation detail) and the first 4 (32 bit) or 8 (64 bit) bytes will be a pointer to the class of the object and, possibly, some metadata encoded into said pointer (i.e. don't just grab the isa and think you've got a valid class).
An object may be in the readonly memory that is mapped into memory by dyld. These objects are actually created by the linker and are a part of the executable. NSString constants fall into this category. NSArray and NSDictionary constants do not; they are still dynamically allocated as per (1) above. Note one oddity; because they are not allocated, they do not follow the string 16 byte (typically) aligned allocation patterns of (1). In fact, they may be 2 byte aligned (they won't likely be odd, but that's another implementation detail that may change).
They may be a tagged pointer. If the lowest order bit is set-- an odd address-- that means "tagged pointer". But that, too, is an implementation detail that can-- and has-- changed. With a tagged pointer, there is no allocation at all. The "pointer" isn't a pointer at all. The pointer is the data; for an NSNumber, the value and type of the contained number is encoded in the object "pointer".
The one exception is a Block. They can be in the heap, in the memory mapped data segment loaded by the executable, or on the stack.
However, that's another implementation detail. Only, in this case, you are exposed to it. While the compiler, under ARC, actually makes it largely fully automatic at this time, there are still a couple of cases where you need to copy a block to ensure it moves to the heap before the declarative scope disappears.
However, since the class of a Block isn't exposed nor is there any means of manually allocating Blocks, I'm going to stick with Objective-C objects never being on the stack. ;)

Related

Objective-C NSString memory leak with objc_setAssociatedObject

I found a memory leak for NSString with objc_setAssociatedObject
Test Code:
int i = 0;
while (YES) {
#autoreleasepool {
NSString *string = [[NSString alloc] initWithFormat:#"%d", i];
// Comment this line. Then the memory leak is gone.
objc_setAssociatedObject(string, "key", [[NSObject alloc] init], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
i++;
}
NSObject can't release. Not sure for NSString.
If I comment the code objc_setAssociatedObject(string, "key", [[NSObject alloc] init], OBJC_ASSOCIATION_RETAIN_NONATOMIC);. There is no memory leak.
Does anyone know what happened?
Maybe related to Tagged Pointer Strings
Tagger Pointer Strings are actually invalid 64 bit pointers where the content is stored within the pointer itself
this helps prevent unnecessary memory allocation
They are invalid pointers in the sense that they don't point to any real memory value
"""Objects are aligned in memory, such that their address is always at least a multiple of the pointer size, and in practice typically a multiple of 16. Object pointers are stored as a full 64-bit integer, but this alignment means that some of the bits will always be zero.
Tagged pointers take advantage of this fact to give special meaning to object pointers where those bits are not zero. In Apple's 64-bit Objective-C implementation, object pointers with the least significant bit set to one (which is to say, odd numbers) are considered tagged pointers. Instead of doing the standard isa dereference to figure out the class, the next three bits are considered as an index into a tagged class table. This index is used to look up the class of the tagged pointer. The remaining 60 bits are then left up to the tagged class to use as they please."""
This is a beautiful hack.
I think for NSTaggedPointerString teh associated objects might be getting cleared in the next runloop

Go memory layout compared to C++/C

In Go, it seems there are no constructors, but it is suggested that you allocate an object of a struct type using a function, usually named by "New" + TypeName, for example
func NewRect(x,y, width, height float) *Rect {
return &Rect(x,y,width, height)
}
However, I am not sure about the memory layout of Go. In C/C++, this kind of code means you return a pointer, which point to a temporary object because the variable is allocated on the stack, and the variable may be some trash after the function return. In Go, do I have to worry such kind of thing? Because It seems no standard shows that what kind of data will be allocated on the stack vs what kind of data will be allocated on the heap.
As in Java, there seems to have a specific point out that the basic type such as int, float will be allocated on the stack, other object derived from the object will be allocated on the heap. In Go, is there a specific talk about this?
The Composite Literal section mentions:
Taking the address of a composite literal (§Address operators) generates a unique pointer to an instance of the literal's value.
That means the pointer returned by the New function will be a valid one (allocated on the stack).
Calls:
In a function call, the function value and arguments are evaluated in the usual order.
After they are evaluated, the parameters of the call are passed by value to the function and the called function begins execution.
The return parameters of the function are passed by value back to the calling function when the function returns.
You can see more in this answer and this thread.
As mentioned in "Stack vs heap allocation of structs in Go, and how they relate to garbage collection":
It's worth noting that the words "stack" and "heap" do not appear anywhere in the language spec.
The blog post "Escape Analysis in Go" details what happens, mentioning the FAQ:
When possible, the Go compilers will allocate variables that are local to a function in that function's stack frame.
However, if the compiler cannot prove that the variable is not referenced after the function returns, then the compiler must allocate the variable on the garbage-collected heap to avoid dangling pointer errors.
Also, if a local variable is very large, it might make more sense to store it on the heap rather than the stack.
The blog post adds:
The code that does the “escape analysis” lives in src/cmd/gc/esc.c.
Conceptually, it tries to determine if a local variable escapes the current scope; the only two cases where this happens are when a variable’s address is returned, and when its address is assigned to a variable in an outer scope.
If a variable escapes, it has to be allocated on the heap; otherwise, it’s safe to put it on the stack.
Interestingly, this applies to new(T) allocations as well.
If they don’t escape, they’ll end up being allocated on the stack. Here’s an example to clarify matters:
var intPointerGlobal *int = nil
func Foo() *int {
anInt0 := 0
anInt1 := new(int)
anInt2 := 42
intPointerGlobal = &anInt2
anInt3 := 5
return &anInt3
}
Above, anInt0 and anInt1 do not escape, so they are allocated on the stack;
anInt2 and anInt3 escape, and are allocated on the heap.
See also "Five things that make Go fast":
Unlike C, which forces you to choose if a value will be stored on the heap, via malloc, or on the stack, by declaring it inside the scope of the function, Go implements an optimisation called escape analysis.
Go’s optimisations are always enabled by default.
You can see the compiler’s escape analysis and inlining decisions with the -gcflags=-m switch.
Because escape analysis is performed at compile time, not run time, stack allocation will always be faster than heap allocation, no matter how efficient your garbage collector is.

iOS/Obj C: Variable allocations and release

I would like to print (log) what are the below variables are stored in stack and heap. I want to know where are these below variables are stored in this program. My feel is, except the first two variables , others are storing in heap.
-(void) MyFunction
{
flat value = 9.5; // Stored in Stack?
int count; // Stored in Stack?
NSString *myString = #"Incoming message"; // Stored in Heap
NSArray *myArr = [[NSArray alloc] init]; // Stored in Heap
.......
.......
}
In this case, how do i release those, using 'release'?
How can i print/log where these variables stored in stack/heap?
Does my assumption storing location(heap/stack) mentioned in above program is correct or wrong?
If an allocated objects stored in heap memory, their references will also be in heap only (or) reference will be in stack?
I would like to print (log) what are the below variables are stored in stack and heap. I want to know where are these below variables are stored in this program.
It's very unlikely that you really want to do that, but you can like this:
NSLog(#"value:%p", &value);
NSLog(#"count:%p", &count);
NSLog(#"myString:%p", myString);
NSLog(#"myArr:%p", myArr);
Regarding where they're stored:
float value = 9.5; // Stored in Stack?
Probably, if you actually modify it. It might also be stored in a register. Or it might be completely optimized away if it turns out to be constant. The above log statements will force it to be stored on the stack (so it can have an address), so asking where the variable is stored can actually change where it is stored.
But yes, as a back-of-the-envelope approximation of unoptimized code, automatic variables are stored on the stack.
int count; // Stored in Stack?
Again, probably. Of course if you never access it, it could be completely optimized away.
NSString *myString = #"Incoming message"; // Stored in Heap
The constant string that this points to is stored in the text segment (in the code itself). The myString pointer itself is an automatic variable, however, and that is stored on the stack as above.
NSArray *myArr = [[NSArray alloc] init]; // Stored in Heap
This could be optimized down to a constant empty array stored in the framework. Or it could be on the heap.
In this case, how do i release those, using 'release'?
No. You manage these using ARC, which will manage retains and releases for you. You should not manually call release in most code.
If an allocated objects stored in heap memory, their references will also be in heap only (or) reference will be in stack?
The pointer variable itself is stored on the stack.
You can log the values of pointer variables with the %p format specifier, e.g.: NSLog(#"%p", myString);
However that in itself won't tell you whether a given address is in a particular memory segment (though you can generally make some educated guesses based on address ranges -- for example, stack addresses begin at the end of a program's address space, so their values tend be much larger than heap addresses; distinguishing heap addresses from static addresses can be a little tricker though).
You're correct in thinking that value and count will be store on the stack, but the object myString refers to will be stored in static memory rather than in heap. However, myArr will be allocated in heap.
Automatic variables (method and function arguments, and local variables not explicitly declared static) are allocated on the stack, regardless of the values you initialize them with.

Why does object have a pointer and not an int?

If we type
MyObject *obj = [[MyObject alloc] init];
"obj" is a pointer to the memory address.
...When we create an int, we type:
int x = 10;
Why don't we type?
int *x = 10;
The question is, why do we need a pointer to object and not int, float, etc...
Efficiency.
Moving an int from one place to another is easy. Moving an object needs a little bit more work from the CPU. Moving the address of an object is as easy as moving an int.
In plain C, it is common to handle pointers to structs for the same reason. C makes it easy with the -> operator.
There are languages where you can create objects “without a pointer”, on the stack. C++, for example. One great thing about having objects on the stack is that they get automatically deallocated when the scope ends, which helps with memory management. It’s also faster.
One bad thing about having objects on the stack is that they get automatically deallocated when the scope ends and the stack disappears. And since objects are usually longer-lived than local variables, you would have to copy the object’s memory somewhere. It’s entirely possible, but it complicates matters.
And it’s not just the memory lifecycle that’s complicated with stack-based objects. Consider assignment, foo = bar for two object types. If the objects are always pointers (Class*), you just assigned a pointer and got two pointers to the same objects; easy. If foo is stack-based (Class), the assignment semantics starts to get blurry – you could well end with a copy of the original object.
Introducing a rule that all objects are allocated on the heap (“with pointers”) is a great simplification. And as it happens, the speed difference doesn’t matter that much, and the compiler can now also automatically insert code to deallocate heap-based objects after they go out of scope, so it’s generally a win-win situation.
You can have pointer for int, float as well.
Objects are created on heap. To access it, you need the address. Thats why they are of pointer types.
Because that is the nature of an object.
Objective-C is directly derrived from C. That is why objects are referred to as pointers. An int-type variable of the size of an memory address is a pointer.
In the end, an object in memory is not much different from an struct in memory.
However, when working in Objective-C it is advisable to think of these variables as references of objects rather than pointers to an object's memory areas. Think of them like Java does and do not spend much thoughts on how the system manages the references. There are far more important things to think of such as alloc/retain vs. release/autorelease or following the much easier ARC rules respectively.
BTW:
MyObject obj;
That would declare an object, not a pointer. It is not possible in Objective-C (afaik) and certainly not reasonable. But if it was reasonable and possible, that is what the syntax would look like.
int *x;
That does create a pointer to an int. For using it you would have to allocate memory and assign its address to x. Rarerly reasonable in Objective C either but quite useful in standard C.
its the difference between objects being on the stack or the heap.
going int x = 10 x is now on the stack. int *x = 10 is just simply wrong (well most likely not what you want) since that is declaring a pointer to address 10 whatever that may be. you would want int *x = malloc(sizeOf(int)); as CodaFi suggested. that will allocate memory on the heap of the size of an int.
going MyObject *obj = [[Myobject alloc] init]; the compiler behind the scenes is allocating your object to the heap for you, but its basically the same principle

What's the size of a reference on the CLR

I was (purely out of curiosity) trying to find out what the size of an actual reference is when an allocation is made on the stack.
After reading this I still don't know (this answers it only for value types or type definitions), and I still cannot seem to find it anywhere.
So basically imagine a class as follows
class A
{
string a;
}
Now when an object of type A is instantiated, a reference to the string object would be stored on the stack, now what would the size of the allocation on the stack be?
Disclaimer: If I'm talking complete and utter nonsense please let me know :)
Just like the size of pointers, presumably, the size would be that of a native int: 32-bits on 32-bit platforms and 64-bits on a 64-bit platform.
It will be the size of IntPtr, either 32 or 64 bits, depending upon your environment.
Now when an object of type A is instantiated, a reference to the string object would be stored on the stack, now what would the size of the allocation on the stack be?
The string reference would in fact be stored on the heap, not the stack, since A is a reference type.

Resources