Instruments (Leaks) and NSDateFormatter

2020-03-24 04:01发布

问题:

When I run my iPhone app with Instruments Leaks and parse a bunch of NSDates using NSDateFormatter my memory goes up about 1mb and stays even though these NSDates should be dealloc'd after the parsing (I just discard them if they aren't new).

I thought the malloc (in my heaviest stack trace below) could become part of the NSDate but I also thought it could be memory that only used during some intermediate step in parsing. Does anyone know which one it is or how to find out?

Also, is there a way to put a breakpoint on NSDate dealloc to see if that memory is really being reclaimed?

Here's what my date formatter looks like for parsing these dates:

df = [[NSDateFormatter alloc] init]; 
[df setDateFormat:@"EEE, d MMM yyyy H:m:s z"];

Here's the Heaviest Stack trace when the memory bumps up and stays there:

   0 libSystem.B.dylib  208.80 Kb     malloc
   1 libicucore.A.dylib  868.19 Kb     icu::ZoneMeta::getSingleCountry(icu::UnicodeString const&, icu::UnicodeString&)
   2 libicucore.A.dylib  868.66 Kb     icu::ZoneMeta::getSingleCountry(icu::UnicodeString const&, icu::UnicodeString&)
   3 libicucore.A.dylib  868.67 Kb     icu::ZoneMeta::getSingleCountry(icu::UnicodeString const&, icu::UnicodeString&)
   4 libicucore.A.dylib  868.67 Kb     icu::DateFormatSymbols::initZoneStringFormat()
   5 libicucore.A.dylib  868.67 Kb     icu::DateFormatSymbols::getZoneStringFormat() const
   6 libicucore.A.dylib  868.67 Kb     icu::SimpleDateFormat::subParse(icu::UnicodeString const&, int&, unsigned short, int, signed char, signed char, signed char*, icu::Calendar&) const
   7 libicucore.A.dylib  868.67 Kb     icu::SimpleDateFormat::parse(icu::UnicodeString const&, icu::Calendar&, icu::ParsePosition&) const
   8 libicucore.A.dylib  868.67 Kb     icu::DateFormat::parse(icu::UnicodeString const&, icu::ParsePosition&) const
   9 libicucore.A.dylib  868.67 Kb     udat_parse
  10 CoreFoundation  868.67 Kb     CFDateFormatterGetAbsoluteTimeFromString
  11 CoreFoundation  868.67 Kb     CFDateFormatterCreateDateFromString
  12 Foundation  868.67 Kb     -[NSDateFormatter getObjectValue:forString:range:error:]
  13 Foundation  868.75 Kb     -[NSDateFormatter getObjectValue:forString:errorDescription:]
  14 Foundation  868.75 Kb     -[NSDateFormatter dateFromString:]

Thanks!

回答1:

[df setDateFormat:@"EEE, d MMM yyyy H:m:s z"]; // Remove the `z`

868 Kb will be permanently allocated on iPhone OS 2.2.1 or 3.1.2 (more to come) after a single invocation to "dateFromString" when the z option is used.

A complete article with source code and log file can be read at http://thegothicparty.com/dev/article/nsdateformatter-memory-leak/



回答2:

There may be a problem with NSDateFormatter parsing date strings with time zones because when I changed the formatter pattern to remove the timezone portion the problem disappeared.

I changed it from this:

[df setDateFormat:@"EEE, d MMM yyyy H:m:s z"];

To this:

[df setDateFormat:@"EEE, d MMM yyyy H:m:s"];

But now the problem is the dates don't get the right timezone so I'll have to have to determine the timezone myself.



回答3:

What do you mean by discarding the NSDateFormatters? Do you release them when you are done with them?

df = [[NSDateFormatter alloc] init]; // allocates memory

Your code allocates memory but you need to call

[df release];

when you are done with them. When you allocate (or copy) object its reference count is incremented by one. When you release object (you send release message to it) the reference count goes down by one. When the reference count reaches 0 the object is deallocated.

If you don't send it release message it will stay in memory and you have memory leak.