0

Currently I'm investigating a memory leak issue in some code written in MRC (Manual Reference Counting, non-ARC).

To check Xcode's measurement tool against my code, I intentionally removed "release" from one the class method (stepSimulation, periodically called in the platform) and was hoping to see "memory leak" in the measurement's memory leak monitor. The thing is, in iOS target, Xcode's measurement correctly detects "memory leak" exactly from the method that misses "release". (The stack trace narrows down to that method correctly.)

However, in OSX target, the measurement doesn't detect any memory leaks. Even after quite long time run, the memory usage doesn't increase at all, it runs just as if it was built with ARC.

Also I have tested few more things in MRC; intentionally over-releasing variable to cause crash. The code behaves correctly as MRC dictates, it crashes in iOS, but it doesn't crash in OSX. I have checked retainCount, too, (I know retainCount not only reflects users' access but also systems', too.) Somehow, the retainCount in OSX never changes, on the contrary it changes as expected in iOS.

Basically the code in iOS target runs exactly as MRC says, but it doesn't in OSX.

I suspect if I had missed any options to build target in OSX, but I am pretty sure that the code is built without ARC in both OSX and iOS, otherwise the compiler would have complained against using "release". Also I have added the compiler flag "-fno-objc-arc" to the "mm file" of that class.

Are there any further options in Xcode that I have to set to build "MRC" binary correctly in OSX? I know this is a kind of question hard to answer unless a lot of information regarding Xcode settings provided, however, I wonder if there's anyone who had similar issues before and know some tips. If so, much appreciated if I could share the info.

OSX: macOS BigSur v11.2.3, iMac-2017
iOS: v12.5.4, iPhone6
Xcode: v12.5.1(12E507)

@interface SomeClass : NSObject{
    NSDate* _lastStepTime;
}
.....
-(id) init;
-(void) stepSimulation; // called periodically at every frame cycle
@end


@implementation SomeClass

-(id) init{
...
     _lastStepTime = [[NSDate alloc] init];
...
}

.......

-(void) stepSimulation
{
    // rc: currentTime's refererence count
    NSDate* currentTime = [[NSDate alloc] init];  // rc = 1
    
    NSTimeInterval timeInterval = [currentTime timeIntervalSinceDate:_lastStepTime];
    
    // do some processing upon the given time interval 
    someProcessingForTimeInterval(timeInterval);
    
    // update the time mark
    [_lastStepTime release];
    
    _lastStepTime = [currentTime retain];  // rc = 2
    
    // removing "release" to intentionally create memory leak;
    // [currentTime release];
}

@end
s4mt6
  • 143
  • 1
  • 2
  • 9
  • 1
    Does `[[NSDate alloc] init]` return a [Tagged Pointer](https://stackoverflow.com/questions/20362406/tagged-pointers-in-objective-c)? – Willeke Jul 12 '21 at 08:01
  • Thank you so much for your reply. As you advised, I did some investigation regarding "tagged pointer" by tracing the pointer of the instance, and have found that NSDate instance in my code, in my OSX platform seems like a tagged pointer and it overrides traditional MRC retain/release rules, although it is not in my iOS platform. Several unofficial documents (online) mention NSDate, NSNumber, NSString, those classes are now with tagged pointers in some platform environments. Are there any Apple's official documents about this? Thanks again for your reply. – s4mt6 Jul 12 '21 at 18:20
  • 1
    The only Apple "documentation" I could find is WWDC 2020 video [Advancements in the Objective-C runtime](https://developer.apple.com/videos/play/wwdc2020/10163/). Tagged pointers are mentioned in some release notes and headers. – Willeke Jul 13 '21 at 00:00
  • Thanks for the info. Much appreciated! – s4mt6 Jul 13 '21 at 00:22

0 Answers0