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

aLoC

macrumors 6502a
Nov 10, 2006
726
0
yes, i have content view set up in Interface Builder... but isn't that what i'm calling in the awakeFromNib?

You shouldn't have to set outlets like that in awakeFromNib, just drag the lines around in Interface Builder. The only reason to do it programatically is if you want to dynamically swap views in and out at runtime.
 

Darkroom

Guest
Original poster
Dec 15, 2006
2,445
0
Montréal, Canada
You shouldn't have to set outlets like that in awakeFromNib, just drag the lines around in Interface Builder. The only reason to do it programatically is if you want to dynamically swap views in and out at runtime.

i have one single view that changes depending on if it's full screen mode or window mode.

so my AppController's Awake from nib actually looks like this:

Code:
- (void)awakeFromNib
	{
	if ([[prefsRadioGroup cellWithTag:1] state] == NSOnState)  [COLOR="SeaGreen"]//if "Window Mode" is selected in prefs as start up[/COLOR]
		{
		SetSystemUIMode(kUIModeNormal, 0);
		[mainWindow2 setAlphaValue:0.0];
		[mainWindow2 makeKeyAndOrderFront:nil];
		[mainWindow2 [COLOR="Red"]setContentView:normalscreenView[/COLOR]];
		timer = [[NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(normalScreenfadeIN2:) userInfo:nil repeats:YES] retain];
		}

	if ([[prefsRadioGroup cellWithTag:2] state] == NSOnState)  [COLOR="SeaGreen"]//if "Full Screen Mode" is selected in prefs as start up[/COLOR]
		{
		SetSystemUIMode(kUIModeNormal, 0);
		SetSystemUIMode(kUIModeAllHidden, 0);
		[mainWindow setAlphaValue:0.0];
		[mainWindow makeKeyAndOrderFront:nil];
		[mainWindow setFrame:[[NSScreen mainScreen] visibleFrame] display:YES animate:NO];
		[mainWindow [COLOR="red"]setContentView:fullscreenView[/COLOR]];
		SetSystemUIMode(kUIModeAllSuppressed, 0);
		timer = [[NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(fullScreenfadeIN2:) userInfo:nil repeats:YES] retain];
		}
        }

[EDIT] oddly, i had just noticed that if the app starts up in Full Screen mode, there isn't a leak at "[mainWindow setContentView:fullscreenView];" (which i assumed there would be since it should match the leaky "[mainWindow2 setContentView:normalscreenView];")... fullscreenView and normalscreenView are both outlets to the same, single NSView in my application... as expected, maybe, if the app starts in full screen mode, once i change from full screen mode to window mode, the "[mainWindow2 setContentView:normalscreenView];" leak appears as usual...

[EDIT again] i just got rid of normalscreenView and fullscreenView by merging them as mainView... it was kinda dumb to have two when only one was needed... now Instruments is only listing 2 leaks... same kinda, but at least now there's only 2 (instead of 4)... so i'm now down from 128 bytes to 64 bytes... not bad so far :p
 

Enuratique

macrumors 6502
Apr 28, 2008
276
0
Just keep in mind that releasing a non-nil object more times than it has been retained will cause errors. This includes calling autorelease on the object multiple times.

Yes, I realize this... But I feel like people are misunderstanding what I am saying. Calling release on a pointer too many times in code that's NOT in the dealloc method is bad because there is the potential that code in the class will try to use that pointer and it is no longer valid. However, calling release on a pointer in the dealloc I consider to be safe because theoretically once you're in the dealloc method, that object is being deconstructed/released and no more code in the object will use that pointer (that is until a new instance of the object is initialized, but then you're getting a whole new set of pointers).

Correct me if I'm wrong, but unless you pass a pointer into the constructor of the object and release it in the dealloc method, I see nothing wrong with a safety release in dealloc (even if it may not truly be necessary).
 

aLoC

macrumors 6502a
Nov 10, 2006
726
0
[EDIT] oddly, i had just noticed that if the app starts up in Full Screen mode, there isn't a leak at "[mainWindow setContentView:fullscreenView];" (which i assumed there would be since it should match the leaky "[mainWindow2 setContentView:normalscreenView];")... fullscreenView and normalscreenView are both outlets to the same, single NSView in my application... as expected, maybe, if the app starts in full screen mode, once i change from full screen mode to window mode, the "[mainWindow2 setContentView:normalscreenView];" leak appears as usual...

That sounds like a good lead to follow up on.
 

aLoC

macrumors 6502a
Nov 10, 2006
726
0
Correct me if I'm wrong, but unless you pass a pointer into the constructor of the object and release it in the dealloc method, I see nothing wrong with a safety release in dealloc (even if it may not truly be necessary).

Doesn't it depend on what NSObject::release does? If it is something like this:
Code:
- (void)release
{
   count--;
   if ( count == 0 ) {
       [self dealloc];
       free(self);
   }
}

Then calling release too many times would cause the C function free() to get doubly called on the same pointer which the OS won't like.

Edit: I guess it depends if it has == 0 or not, which we don't know.
 

Enuratique

macrumors 6502
Apr 28, 2008
276
0
Then calling release too many times would cause the C function free() to get doubly called on the same pointer which the OS won't like.

As far as I'm aware, calling free() on a pointer that's already been released does not make the operating system complain... When it looks up the memory address in the memory map, and doesn't find it (since it has already been freed), then it just exits.

[EDIT]From the free man page: free() frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behaviour occurs. If ptr is NULL, no operation is performed.

Now, if by random chance, a new allocation received the exact same address (in another part of the application or a different app entirely), then you could have problems, but there may (or may not) be protections in place to prevent such a thing from happening.

[EDIT]This may be the undefined behavior the man page refers to (freeing a pointer that you technically don't own or weren't responsible for allocating)
 

admanimal

macrumors 68040
Apr 22, 2005
3,531
2
As far as I'm aware, calling free() on a pointer that's already been released does not make the operating system complain... When it looks up the memory address in the memory map, and doesn't find it (since it has already been freed), then it just exits.

[EDIT]From the free man page: free() frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behaviour occurs. If ptr is NULL, no operation is performed.

Now, if by random chance, a new allocation received the exact same address (in another part of the application or a different app entirely), then you could have problems, but there may (or may not) be protections in place to prevent such a thing from happening.

[EDIT]This may be the undefined behavior the man page refers to (freeing a pointer that you technically don't own or weren't responsible for allocating)

Usually things that are said to have "undefined behavior" end up causing bus errors or seg faults.
 

aLoC

macrumors 6502a
Nov 10, 2006
726
0
Yes you are right, it doesn't crash, it just prints a message to the console. (but I suppose it is one of those things that could change from run to run)

Code:
#include <stdlib.h>
#include <stdio.h>

int main()
{
  char * buf=malloc(10);
  free(buf);
  free(buf);

  printf("I did not crash\n");

  return;
}

$ gcc test.c -o test
$ ./test
test(9070) malloc: *** error for object 0x100120: double free
*** set a breakpoint in malloc_error_break to debug
I did not crash
$
 

admanimal

macrumors 68040
Apr 22, 2005
3,531
2
Code:
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // insert code here...
    NSLog(@"Hello, World!");
	NSNumber *num = [[NSNumber alloc] initWithInt:42];
	[num release];
	[num release];
	
	
    [pool drain];
    return 0;
}

This code gets the same message as your C version.
 

aLoC

macrumors 6502a
Nov 10, 2006
726
0
This code gets the same message as your C version.

The real NSObject::release musn't have the == 0 guard clause of my guess version. If they expected people to exactly balance their releases/allocs it would make sense to let the error happen.
 

Enuratique

macrumors 6502
Apr 28, 2008
276
0
Code:
#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // insert code here...
    NSLog(@"Hello, World!");
	NSNumber *num = [[NSNumber alloc] initWithInt:42];
	[num release];
	[num release];
	
	
    [pool drain];
    return 0;
}

This code gets the same message as your C version.

Wow, good to know! Thanks guys... I looked back over my code and I rarely have pointers that get allocated that aren't around for the life of the class so I haven't run into this. The few times that I do, I make sure to release them when appropriate and not in dealloc.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.