Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

TurboLag

macrumors member
Original poster
Feb 24, 2004
85
0
I am curious, if you call a method which returns an object, but you dont store it anywhere, does it still exist on the stack forever, creating a memory leak?

Ex.

- (NSString *)getString; //method prototype

[myObject getString];
 

gnasher729

Suspended
Nov 25, 2005
17,980
5,566
I am curious, if you call a method which returns an object, but you dont store it anywhere, does it still exist on the stack forever, creating a memory leak?

Ex.

- (NSString *)getString; //method prototype

[myObject getString];

There is no way to return an Objective-C object. You can only return a _pointer_ to an Objective-C object. Whether the object behind the pointer continues to exist depends on its retain count. You'll have to read the Cocoa documentation about when to release or not release objects. According to Cocoa guidelines, a method named "getString" will return an existing object without increasing its retain count (or an autoreleased object), so you need to retain it if you want to keep it, or do nothing if you don't want to keep it.
 

TurboLag

macrumors member
Original poster
Feb 24, 2004
85
0
Ah, yes your right, only the pointer gets passed.

I guess what I am asking is, is the memory required for the pointer (4/8 bytes) leaked when it gets pushed on the stack, and nothing pops it?
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
When a method returns a pointer, you need a place to store it. That means the calling method needs to have a pointer already defined to store the address that is returned. If you use the same pointer over and over again, you may be leaking memory for another reason since you won't have a way to send release to an object you no longer have a reference to. However, if you never send retain to these objects, you should be fine.

Code:
NSString *x = nil;
x = [MyObject getString];
NSLog(x);
x = [MyObject getString];
NSLog(x);
x = [MyObject getString];

x is on the stack, using up some number of bytes based on the platform. You've assigned to it 3 times, but it's always using the same memory to store the value you've assigned. What's on the other end of that pointer is a totally different story. gnasher729 pointed out that by convention getString would return something without increasing that object's retain count, and simply assigning its pointer to a variable will not do anything to change that.

It may help to think of it like this. You have declared an int in a function. That int is on the stack. You assign 5 to this int, then 7, then 9, then 34032. That int isn't using extra memory on the heap (or stack) because you assigned things to it. A pointer will work the same way.

-Lee
 

Catfish_Man

macrumors 68030
Sep 13, 2001
2,579
2
Portland, OR
I guess what I am asking is, is the memory required for the pointer (4/8 bytes) leaked when it gets pushed on the stack, and nothing pops it?

How on earth are you getting into a situation where nothing pops the stack?
 

TurboLag

macrumors member
Original poster
Feb 24, 2004
85
0
I dont think Im making myself clear.

Lets say there is a method which does something (which I need to happen), and then passes a pointer to an object, which I dont care about.

- (NSString *)method{
//do something here
return @"a pointer to this string is pushed onto stack";
}

// in my code...
[self method];
//I call the method, it does what it should, then passes back something to //which I dont care for. Does the pointer still remain on the stack, causing a //leak?
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
If you don't do anything with what is returned, nothing is placed on the stack or the heap (where would it go?). The memory address that is returned is what the expression:
Code:
[self method];
evaluates to, but since this expression isn't used as the right hand value of an assignment, etc. it just "goes away". Here is a simple C program:
Code:
int getInt(void);

int main(int argc, char *argv[]) {
  getInt();
}

int getInt(){
  return 5;
}

Here is the assembly that is produced:
Code:
        .file   "testret.c"
        .text
.globl main
        .type   main, @function
main:
        leal    4(%esp), %ecx
        andl    $-16, %esp
        pushl   -4(%ecx)
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ecx
        subl    $4, %esp
        call    getInt
        addl    $4, %esp
        popl    %ecx
        popl    %ebp
        leal    -4(%ecx), %esp
        ret
        .size   main, .-main
.globl getInt
        .type   getInt, @function
getInt:
        pushl   %ebp
        movl    %esp, %ebp
        movl    $5, %eax
        popl    %ebp
        ret
        .size   getInt, .-getInt

Nothing is done back in main with %eax after the call to getInt. If another function was called, %eax would just be reused (hard to think of a stack in this case, since registers are being used, but the result is the same) as needed.

In your example, you use an NSString literal as the return value. NSString literals are auto-released as far as I know, so in your example you should be fine memory-wise. Are you seeing behavior that makes you think otherwise?

Based on your comment, i think your discussion about the stack is in regard to how the return value is passed back to the caller. This is implementation specific, but you don't need to worry about leaking memory by calling non-void functions and discarding their return values.

-Lee
 

TurboLag

macrumors member
Original poster
Feb 24, 2004
85
0
Great answer, lee1210.

It is out of curiosity. I just wanted to know if it creates a leak, as there are a few occasions where I call a method, and ignore its return.
Thanks!
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
You have to be careful if you are calling things that return a "new" Object, with a retain count. This seems odd, but if you did:
Code:
NSString *myString = @"My string";
[myString copy];
[myString copy];
[myString copy];

you'd have a leak on your hands. You are safe to discard return values if they are primitives, or if they return pointers to objects that you don't own. Methods with names containing:
alloc
copy
copyWithZone
new

Return something that you own, so if you discard their return values you will be leaking. Not because you're not doing something special with the pointer returned, but because you've discarded this pointer, so you will have no way to send release to these objects.

-Lee
 

Soulstorm

macrumors 68000
Feb 1, 2005
1,887
1
One thing you may have forgotten is that Cocoa provides autorelease pools that release autorelased objects when the Cocoa runtime decides it. In methods where you return pointers to objects, it is wiser to return autoreleased objects. Like this:

HTML:
- (NSString *)foo(){
	NSString *str = [[NSString alloc]initWithString:@"hello world!"];
	return [str autorelease];
}

That way the string you created will be returned, used by you, and when it's no longer needed, it will be thrown away the next time Cocoa decides to release its internal autorelease pools. So, you won't need to worry about deallocating a non-needed object.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.