-1

Below is my code include a thread.This thread take care the queue size,if size > 10 then log and remove the last object.But when I run demo=[[myDemo alloc]init] to start thread,and get exception message="EXC_BAD_ACCESS".Have any guy help me to solve this problem?

   @interface myDemo:NSObject
    {
        NSMutableArray  *q;
        NSThread        *thread;
        bool            running;
    }

    -(void)putData:(NSData *)data;
    -(NSData *)popData;
    -(void)stopThread;
    @end;

@implementation myDemo
    -(id)init
    {
        if(NULL!=(self = [super init]))
        {
            q=[NSMutableArray array];
            thread=[[NSThread alloc] initWithTarget:self
                                           selector:@selector(myThreadMainMethod:)
                                             object:nil];
            [thread start];
        }
        return self;
    }
    -(void)myThreadMainMethod:(id)object
    {
        unsigned long count;
        NSData *data;
        if(running) return;
        running=true;
        while(running)
        {
            @synchronized(self)
            {
                count=[q count];//crash !!!!
                if(count>10)
                {
                    data=[q lastObject];
                    NSLog(@"count=%d ,remove last data=%@",count,[[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]);
                    [q removeLastObject];

                }
            }
        }
        running=false;
    }

putData and popData are access the queue by @synchronized(self)

-(void)putData:(NSData *)data
{
    @synchronized(self)
    {
        [q addObject:data];
    }
}
-(NSData *)popData
{
    NSData * data=NULL;
    unsigned long count;
    @synchronized(self)
    {
        count=[q count];
        if(count!=0)
        {
            data=[q lastObject];
            [q removeLastObject];
        }
    }
    return data;
}
luckfox0927
  • 81
  • 1
  • 4

4 Answers4

1

Try to initialize "q" ivar with a +1 retain count non-autoreleased object, like this:

- (id)init
{
    if (self = [super init])
    {
        q = [[NSMutableArray alloc] initWithCapacity:10];
        thread = [[NSThread alloc] initWithTarget:self
                                         selector:@selector(myThreadMainMethod:)
                                           object:nil];
        [thread start];
    }
    return self;
}

Also you have to put all the code that will run on background thread into @autoreleasepool or NSAutoreleasePool. I think your program runs out of memory somehow. Example:

- (void)myThreadMainMethod:(id)object
{
    @autoreleasepool {
        static unsigned long count;
        NSData *data = nil;
        if (running) {
            return;
        }
        running = true;
        while (running)
        {
            @synchronized(self)
            {
                count=[q count];//crash !!!!
                if(count>10)
                {
                    data=[q lastObject];
                    NSLog(@"count=%d ,remove last data=%@",count,
                          [[[NSString alloc] initWithData:data
                                                 encoding:NSUTF8StringEncoding]
                          autorelease]);
                    [q removeLastObject];
                }
            }
            running=false;
        }
    }
}

Also there's a problem with synchronization of ivars in your class. You are synchronizing self, but you are using "running" outside of synchronization scope. Also, the logic of the loop is unclear, you are running the loop just once, why do you need it at all?

art-divin
  • 1,635
  • 1
  • 20
  • 28
1

AFAIK [NSArray array] returns an autoreleased object. Though I just don't find a reference for that. I think you should retain it in the init method as you don't ARC.

Hermann Klecker
  • 14,039
  • 5
  • 48
  • 71
0

I rewrite thread code as below.thread was crash after "while loop" run 564 times

 -(void)myThreadMainMethod:(id)object
    {
        unsigned long count,index=0;
        NSData *data;
        NSMutableArray *q1;
        if(running) return;
        running=true;

        q1=[NSMutableArray array];
        while(running)
        {   
            @synchronized(self)
            {

                count=[q count];//crash !!!
                NSLog(@"#%d count=%d ",index++,count);

            }
        }
    }

then I rewrite again as below

-(void)myThreadMainMethod:(id)object
    {
        unsigned long count,index=0;
        NSData *data;
        NSMutableArray *q1;
        if(running) return;
        running=true;

        q1=[NSMutableArray array];
        while(running)
        {   
            @synchronized(self)
            {

                count=[q1 count];//run fine
                NSLog(@"#%d count=%d ",index++,count);       
            }
        }
    }

run fine...WHY?

luckfox0927
  • 81
  • 1
  • 4
  • try to edit your original question rather than adding an answer to your own question without actual answer. What about your problem: You are managing threads in a very wrong fashion. Try reading this guide: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html – art-divin Jun 28 '13 at 09:55
0

is it not because NSMutableArray *q1; should be used as count=[q1 count]; and not count=[q count]; because it is declared as q1 and not q???

ebdo
  • 157
  • 3
  • 14