How to release NSThread object thoroughly? - objective-c

Like this title, I want know how to release NSThread object thoroughly.
This is my code:
for(int i = 0; i < 10; i++){
NSThread * thread = [[NSThread alloc] initWithBlock:^{
#autoreleasepool {
sleep(3);
NSLog(#"ended");
}
}];
thread.name = #"asdf";
[thread start];
}
thread will be released after execution. But "Instruments" tells me that thread still has 512kb of space in memory, and that the method is [thread start].
Instruments output
Can I release this space, and if so, how?

Related

autoreleased pool explanation

In my code i am working with audio buffers, when i have a callback function that is being called many times per second. this callback is in a class that handle audio, and not in the main class of the app .
At the start i was getting this warning that is being log many times during callbacks:
Object 0x93cd5e0 of class __NSCFNumber autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool()
Then i was told to put this line in the callback func :
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
then this error disappeared .
But i cant understand how is that possible that i alloc the pool so many times in 1 second- and maybe i have a memory issues.
I saw than that i have to put this at the end :
[pool drain];
so i have this :
OSStatus status;
status = AudioUnitRender(audioUnit,
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
&bufferList);
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // that line added
//run on evert sample
int16_t *q = (int16_t *)(&bufferList)->mBuffers[0].mData;
for(int i=0; i < inNumberFrames; i++)
{
static int stateMachineSelector=1;
static int sampelsCounter=0;
// CODE TO HANDLE THE SAMPLES ...
}
[pool drain]; // issue here
what exactly i did here?
why is that ?
is that ok from memory aspect ?
thanks a lot .
When starting a Autorelease pool with [[NSAutoreleasePool alloc] init] all further objects receiving a autorelease or where created with the convenience allocator (like NSArray *ary = [NSArray array];, or UIView *view = [[[UIView alloc] init] autorelease]; are in that pool.
So:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *ary = [NSArray array];
[pool release]; // this will also release and dealoc the *ary from memory
If you have a callback running NOT no the main thread, you SHOULD do a new pool. If not, your objects may leek to nirvana. :)
If you process a lot of data with autorelease objects and you'd like to free the memory, then create a pool, process, release the pool.

EXC_BAD_ACCESS in nested dispatch_async with an NSAutoreleasePool

I have some code which is similar to the following code:
dispatch_queue_t queue = dispatch_queue_create("", 0);
dispatch_queue_t inner_queue = dispatch_queue_create("", 0);
dispatch_async(queue,
^{
NSAutoreleasePool* autoreleasePool = [[NSAutoreleasePool alloc] init];
NSArray* objects = [self.otherObject getObjectsFromSlowQuery];
[objects enumerateObjectsWithUsingBlock:^(id anObject, NSUInteger idx, BOOL *stop)
{
[anObject prepare];
dispatch_async(inner_queue,
^{
InnerObject* innerObject = anObject.innerObject;
[self.helper doSomethingExpensiveWithObject:innerObject];
});
dispatch_sync(self.syncQueue,
^{
[self insertIntoCollection:anObject];
});
}];
dispatch_release(inner_queue);
[autoreleasePool drain];
});
dispatch_release(queue);
Where [anObject.innerObject] is a nonatomic property.
I got a crash report from a user which shows an EXC_BAD_ACCESS in objc_msgSend() when trying to access a property of innerObject within the doSomethingExpensiveWithObject: call.
At first I was thinking that perhaps the autoreleasePool was drained so the innerObject instance was released before returning from doSomethingExpensiveWithObject: but as far as I know anObject should be retained by the inner dispatch_async call which should also keep the innerObject alive.
What am I missing?
Instruments will make quick work of this - run with zombies and review the reference counts when it stops.

Who owns autorelease objects?

In objective-c manual it is written that something like
return [[[SomeClass alloc] init] autorelease];
can be done and then release is not necessary at any point, even not in the function that received this object. Who owns this object then? when will it be released?
The current NSAutoreleasePool does and will take care of the releasing when drained.
IBAction calls get wrapped into an NSAutoreleasePool that gets drained after the call.
For all non-IBAction calls the following would apply:
Say, you have these methods:
- (id)foo {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
SomeClass *bar = [self bar]; //bar still exists here
//do other stuff
//bar still exists here
//do other stuff
//bar still exists here
[pool drain]; //bar gets released right here!
//bar has been released
}
- (id)bar {
return [[[SomeClass alloc] init] autorelease]; //bar will still be around after the return
}
Consider another scenario:
- (void)foo {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
//do other stuff
[self bar];
//do other stuff
[pool drain]; //the string from blee would be released right here;
}
- (void)bar {
[self baz];
}
- (void)baz {
NSString *string = [self blee];
}
- (id)blee {
return [NSString string]; //autoreleased
}
As you can see the autoreleased string object did not even have to be used in or get returned to the scope in which the pool was created.
NSAutoreleasePools exist on a stack (one per thread) and autoreleased objects get owned by the pool that's topmost at the time of the call to autorelease.
Update:
If you are dealing with a tight loop and want to keep the memory moderately low while not slowing down your loop, consider doing something like this:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for (NSUInteger i = 0; i < 1000000000; i++) {
[NSString stringWithString:#"foo"];
if (i % 1000 == 0) {
[pool drain];
pool = [[NSAutoreleasePool alloc] init];
}
}
[pool drain];
However NSAutoreleasePool is highly optimized, so one pool per iteration usually isn't much of a problem.
To fully understand how NSAutoreleasePools work read this excellent article by Mike Ash

writing file with NSFileHandle in NSThread crash app

I attempt to write a file in thread because it freeze my app when writing but when i launch writing process it crash
2011-10-04 21:53:51.022 xxxxxxxxx[2046:6603] *** Terminating app due to uncaught exception 'NSFileHandleOperationException', reason: '*** -[NSConcreteFileHandle seekToEndOfFile]: Operation timed out'
my code:
- (void)WriteTest{
[NSThread detachNewThreadSelector:#selector(DoWriteTest:) toTarget:self withObject:hFile];
}
- (void)DoWriteTest:(NSFileHandle *)aHandle{
int i;
if (aHandle) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(#"---start--- writing test file --");
for (i=0; i<1024*1024; i++) {
[aHandle seekToEndOfFile];
[aHandle writeData:[NSData dataWithBytes:bytes length:(sizeof bytes) - 1]];
usleep(1);
}
NSLog(#"---end--- writing test file");
[pool release];
} else {
NSLog(#"ERROR: writing test file thread");
}
}
when i did this without a thread this code work, can you explain me what i'm wrong please, i make a lot of google search but i don't find a solution. Thanks.
Your code worked for me. My guess is you opened your file handle incorrectly. Also note that you should use [pool drain] instead of [pool release], but this is nitpicking. My full code is below. Comment if you have any questions. Hope it helps.
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
fileHandle = [NSFileHandle fileHandleForWritingAtPath:#"/Users/Drew/Desktop/test.txt"];
[NSThread detachNewThreadSelector:#selector(threadSelector:) toTarget:self withObject:fileHandle];
}
- (void)threadSelector:(NSFileHandle *)aHandle {
if (aHandle) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int i;
for (i=0; i<1024; i++)
{
[aHandle seekToEndOfFile];
char buffer[1024] = "a string ";
[aHandle writeData:[NSData dataWithBytes:buffer length:(sizeof buffer) - 1]];
usleep(1);
}
[pool drain];
}
}

Xcode Objective C - Help with NSAutoreleaseNoPool error using NSThread

Hey experts, I'm having a little trouble with NSThread. Xcode keeps on giving me "* __NSAutoreleaseNoPool(): Object 0x5694dc0 of class NSCFString autoreleased with no pool in place - just leaking" errors.
I'm correctly declaring the pool with the line
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
then at the end of my loop I use:
[pool release];
Is it because I'm using a delegate method as the performSelectorInBackground?
Thanks stackoverflow.
- (void)preFetch { //process filenames to be downloaded and assign types to each one
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *regions = [NSArray arrayWithObjects: #"dr_national", #"ds_ir", #"conus_FL360", #"FL360_conus", #"dr_nw", #"dr_nc", #"dr_ne", #"dr_sw", #"dr_sc", #"dr_se", #"ds_ir_nw", #"ds_ir_nc", #"ds_ir_ne", #"ds_ir_sw", #"ds_ir_sc", #"ds_ir_se", nil];
NSError* error;
for (NSString *regionDir in regions) {
NSLog(#"region now: %#", regionDir); foo = 0;
NSString *regUrl = [NSString stringWithFormat:#"http://someUrl/%#/index.lst", regionDir ];
NSString* text1 = [NSString stringWithContentsOfURL:[NSURL URLWithString:regUrl ] encoding:NSASCIIStringEncoding error:&error];
NSArray *listItems = [text1 componentsSeparatedByString:#"\n"];
for (int k=0; k<[listItems count]; k++) {
if ([[listItems objectAtIndex:k] length] != 0){
NSString *newpath = [NSString stringWithFormat:#"http://someUrl/%#", [listItems objectAtIndex:k]];
NSLog(#"newpath: %#",newpath);
[self performSelectorInBackground:#selector(moveProgressBar) withObject:nil];
[self fetchImages:newpath:type]; //pass multiple arguments to fetchImages, newpath and type
}
}
}
[pool release];
}
- (void)moveProgressBar{
[delegate increaseAmount];
}
You should just set up an autorelease pool in your method, since that's being called on a different thread.
- (void)moveProgressBar
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[delegate increaseAmount];
[pool drain];
}
Edit
Having said that, looking at the code itself, it seems that you might be trying to update the UI from a background thread? Any code that does that should be executed on the main thread.
If you have a long running process that you want to run which doesn't lock the UI, and keeps the user updated on progress, the typical pattern would be to do the processing itself on a background thread, and periodically update the UI using performSelectorOnMainThread:.