Re: Autoreleased Data In Cocoa
Re: Autoreleased Data In Cocoa
- Subject: Re: Autoreleased Data In Cocoa
- From: Matt Patenaude <email@hidden>
- Date: Tue, 31 May 2011 08:45:42 -0700
The Cocoa-created autorelease pool is automatically drained at an unspecified time, typically every few iterations of the run loops. You can trust it to do the right thing.
-Matt
Sent from my iPhone
On May 31, 2011, at 8:32 AM, Bing Li <email@hidden> wrote:
> Dear Nick and all,
>
> Thanks so much for your reply! I am still a new Cocoa developer so that I
> need to improve during the programming procedure.
>
> Now I modify the code and it works fine. The code is as follows.
>
> But I still have a question. If the autoreleased data will keep alive until
> the pool is drained, what if the data is autoreleased in a Cocoa
> auto-created pool? It will keep alive unless the process is shutdown?
>
> Thanks!
> Bing
>
> - (NSString *) receiveMessage
> {
> NSMutableString *receivedString;
> NSString *message;
> [isConnectedLock lock];
> @try
> {
> if (isConnected)
> {
> char buffer[Constants.WWW.BUFFER_SIZE];
> ssize_t numBytesReceived = recv(destinationSocket,
> buffer, Constants.WWW.BUFFER_SIZE, 0);
> if (numBytesReceived <= 0)
> {
> return Constants.WWW.NO_RECEIVED_MESSAGE;
> }
> buffer[numBytesReceived] = '\0';
>
> receivedString = [[NSMutableString alloc]
> initWithBytes:buffer length:numBytesReceived encoding:NSUTF8StringEncoding];
>
> NSRange range = [receivedString
> rangeOfString:Constants.WWW.DELIMITER];
> if (range.location > 0 && range.location <
> [receivedString length])
> {
> message = [receivedString
> substringToIndex:range.location];
> return message;
> }
> else
> {
> while (numBytesReceived > 0)
> {
> NSAutoreleasePool *loopPool =
> [[NSAutoreleasePool alloc] init];
> numBytesReceived =
> recv(destinationSocket, buffer, Constants.WWW.BUFFER_SIZE, 0);
> if (numBytesReceived <= 0)
> {
> [loopPool drain];
> break;
> }
> buffer[numBytesReceived] = '\0';
> NSString *newReceivedString =
> [[[NSString alloc] initWithBytes:buffer length:numBytesReceived
> encoding:NSUTF8StringEn
> coding] autorelease];
> [receivedString
> appendString:newReceivedString];
> range = [receivedString
> rangeOfString:Constants.WWW.DELIMITER];
> if (range.location > 0 &&
> range.location < [receivedString length])
> {
> message = [receivedString
> substringToIndex:range.location];
> [loopPool drain];
> break;
> }
> [loopPool drain];
> }
> }
> return message;
> }
> else
> {
> return Constants.WWW.NO_RECEIVED_MESSAGE;
> }
> }
> @catch (NSException *e)
> {
> NSLog(@"%@", e);
> return Constants.WWW.NO_RECEIVED_MESSAGE;
> }
> @finally
> {
> [isConnectedLock unlock];
> [receivedString autorelease];
> }
> }
>
>
> On Tue, May 31, 2011 at 11:13 AM, Nick Zitzmann <email@hidden> wrote:
>
>>
>> On May 30, 2011, at 8:15 PM, Bing Li wrote:
>>
>>> - (NSString *) receiveMessage
>>> {
>>> NSMutableString *receivedString;
>>> NSString *message;
>>> NSString *newReceivedString;
>>> [isConnectedLock lock];
>>> @try
>>> {
>>> if (isConnected)
>>> {
>>> char buffer[Constants.WWW.BUFFER_SIZE];
>>>
>>> // Receive remote data
>>> ssize_t numBytesReceived = recv(destinationSocket,
>>> buffer, Constants.WWW.BUFFER_SIZE, 0);
>>> if (numBytesReceived <= 0)
>>> {
>>> return Constants.WWW.NO_RECEIVED_MESSAGE;
>>> }
>>> buffer[numBytesReceived] = '\0';
>>>
>>>
>>> // Convert data to NSString locally
>>> receivedString = [[NSMutableString alloc]
>>> initWithBytes:buffer length:numBytesReceived
>> encoding:NSUTF8StringEncoding];
>>> message = [[NSString alloc]
>>> initWithString:Constants.WWW.EMPTY_STRING];
>>
>> Why are you storing a non-autoreleased object to a pointer and then writing
>> over it later?
>>
>>>
>>>
>>> // Since the data has specific formats, some
>> simple
>>> parsing jobs by delimiter are done as follows.
>>>
>>> NSRange range = [receivedString
>>> rangeOfString:Constants.WWW.DELIMITER];
>>> if (range.location > 0 && range.location <
>>> [receivedString length])
>>> {
>>> message = [receivedString
>>> substringToIndex:range.location];
>>
>> Here you're overwriting a pointer to an object you own with an autoreleased
>> object.
>>
>>>
>>> // Return data after parsing
>>> return message;
>>> }
>>> else
>>> {
>>> // Receive remote data continually if the
>>> receivedString is longer than expected
>>> while (numBytesReceived > 0)
>>> {
>>> NSAutoreleasePool *loopPool =
>>> [[NSAutoreleasePool alloc] init];
>>>
>>> // Receive data
>>> numBytesReceived =
>>> recv(destinationSocket, buffer, Constants.WWW.BUFFER_SIZE, 0);
>>> if (numBytesReceived <= 0)
>>> {
>>> return
>>> Constants.WWW.NO_RECEIVED_MESSAGE;
>>
>> Here you're leaking the autorelease pool you created above.
>>
>>> }
>>>
>>>
>>> buffer[numBytesReceived] = '\0';
>>> newReceivedString = [[[NSString
>>> alloc] initWithBytes:buffer length:numBytesReceived
>>> encoding:NSUTF8StringEncoding] autorelease];
>>> range = [receivedString
>>> rangeOfString:Constants.WWW.DELIMITER];
>>> if (range.location > 0 &&
>>> range.location < [receivedString length])
>>> {
>>> message = [receivedString
>>> substringToIndex:range.location];
>>>
>>> // Return data after
>> parsing
>>> return message;
>>
>> Here you're placing a new object in the autorelease pool, and then leaking
>> the autorelease pool.
>>
>>> }
>>> [loopPool drain];
>>> }
>>> }
>>> return Constants.WWW.NO_RECEIVED_MESSAGE;
>>> }
>>> else
>>> {
>>> return Constants.WWW.NO_RECEIVED_MESSAGE;
>>> }
>>> }
>>> @catch (NSException *e)
>>> {
>>> return Constants.WWW.NO_RECEIVED_MESSAGE;
>>> }
>>> @finally
>>> {
>>> [isConnectedLock unlock];
>>>
>>> // Before returning received data, autorelease them here.
>>> [receivedString autorelease];
>>> [message autorelease];
>>
>> Here you're autoreleasing a pointer that may or may not have been
>> autoreleased already.
>>
>> I suggest you re-read the memory management rules again and pay attention
>> to the rules regarding release and autorelease. If anyone tries to re-state
>> it here, we're inevitably going to get something wrong. <
>> http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
>>>
>>
>> Also, I cannot recommend writing an object to a pointer that the program is
>> never going to read. If you're concerned about accidentally accessing an
>> uninitialized pointer, then just set it to nil instead.
>>
>> Nick Zitzmann
>> <http://www.chronosnet.com/>
>>
>>
>>
>>
> _______________________________________________
>
> Cocoa-dev mailing list (email@hidden)
>
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden