在Cocoa中解决EXC_BAD_ACCESS问题?

时间:2011-10-07 18:02:19

标签: objective-c xcode macos cocoa exc-bad-access


嘿..我在可可中有以下方法..

-(void)startUploadWithContainerName:(NSString *)containerName
{
//Make an object of NSFileManager and Fetch an array of local folder contents and cloud folder contents
NSFileManager *uploadManager=[[NSFileManager alloc] init];
NSString *uploadPath=[[[NSString alloc] initWithString:@"~/Cloud Briefcase"] stringByExpandingTildeInPath];
NSError *err;
NSArray *uploadFolderContents=[uploadManager contentsOfDirectoryAtPath:uploadPath error:&err];
ASICloudFilesObjectRequest *cloudList = [ASICloudFilesObjectRequest listRequestWithContainer:containerName];
[cloudList startSynchronous];
NSArray *cloudFolderContents = [cloudList objects];

[cloudList release];
[uploadManager release];

NSLog(@"%lu",[uploadFolderContents count]);
NSLog(@"\n%@\n\n%@",cloudFolderContents,uploadFolderContents);
NSString *notFoundPath;
NSString *foundPath;
NSString *foundCloudMatch;
NSDate *cloudUploadDate;

for (int j=1; j<[uploadFolderContents count]; j++) {
    int i=0;
    for (int k=0; k<[cloudFolderContents count]; k++) {
        if ([[[cloudFolderContents objectAtIndex:k] name] isEqualToString:[uploadFolderContents objectAtIndex:j]]) {
            i=1;
            foundPath=[uploadFolderContents objectAtIndex:j];
            foundCloudMatch=[cloudFolderContents objectAtIndex:k];
            cloudUploadDate=[[cloudFolderContents objectAtIndex:k] lastModified];
            break;
        }
        else{
            i=0;
            notFoundPath=[uploadFolderContents objectAtIndex:j];
            continue;
        }
    }

    if (i==1) {
        NSLog(@"Found In Cloud: %@",foundPath);
        NSString *uploadPath=[[NSString stringWithFormat:@"~/Cloud Briefcase/%@",foundPath] stringByExpandingTildeInPath];
        NSTimeZone *tCST=[NSTimeZone timeZoneWithAbbreviation:@"CST"];
        NSInteger cloudDifference=[tCST secondsFromGMTForDate:cloudUploadDate];

        NSFileManager *typeManager=[[NSFileManager alloc] init];
        NSError *Er;
        NSDictionary *propertiesOfUploadFile=[typeManager attributesOfItemAtPath:uploadPath error:&Er];

        NSDate *localUploadDate=[propertiesOfUploadFile objectForKey:NSFileModificationDate];

        NSInteger sourceUploadDifference=[[NSTimeZone systemTimeZone] secondsFromGMTForDate:localUploadDate];


        NSLog(@"Local Date %@",localUploadDate);
        NSLog(@"Local Difference %ld",sourceUploadDifference);
        NSTimeInterval diff=sourceUploadDifference-cloudDifference;
        NSTimeInterval sDiff=sourceUploadDifference;
        NSDate *lDate=[[NSDate alloc] initWithTimeInterval:sDiff sinceDate:localUploadDate];
        NSDate *comparisonDate=[[NSDate alloc] initWithTimeInterval:diff sinceDate:cloudUploadDate];
        NSLog(@"\nSDiff Value %@",lDate);
        NSLog(@"Comparison Date %@",comparisonDate);

        [localUploadDate release];
        [propertiesOfUploadFile release];
        [typeManager release];
        [tCST release];

        if ([comparisonDate compare:lDate]==NSOrderedAscending) {
            [comparisonDate release];
            [lDate release];
            NSLog(@"Got It");
            NSString *escString=[foundPath stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
            ASICloudFilesObjectRequest *request = 
            [ASICloudFilesObjectRequest putObjectRequestWithContainer:containerName objectPath:escString contentType:@"file" file:uploadPath metadata:nil etag:nil];
            [request startSynchronous];
            NSLog(@"Uploaded %@",foundPath);
        }



    }
    else{
        NSLog(@"Not Found In Cloud: %@",notFoundPath);
        NSString *uploadPath=[[NSString stringWithFormat:@"~/Cloud Briefcase/%@",notFoundPath] stringByExpandingTildeInPath];
        //          NSLog(@"%@",uploadPath);


        NSString *escString=[notFoundPath stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
        NSLog(@"URL ENCODED VALUE: %@",escString);

        ASICloudFilesObjectRequest *request = 
        [ASICloudFilesObjectRequest putObjectRequestWithContainer:containerName objectPath:escString contentType:@"file" file:uploadPath metadata:nil etag:nil];
        [request startSynchronous];
        NSLog(@"Upload Complete");
    }
}
[uploadPath release];

[cloudList release];
[uploadFolderContents release];

 }

但它挂起显示异常

  

收到信号EXC_BAD_ACCESS

任何人都可以解决这个问题吗?例外情况发生在 NSLog(@“发现于云:%@”,foundPath);

4 个答案:

答案 0 :(得分:2)

通常,您将环境变量NSZombieEnabled设置为YES,然后解决问题。 在你的情况下,我看到你已经声明指针而没有指向任何危险的对象。在Clang Analyzer中运行代码会将其报告为警告。 将这些指针设置为nil。你已经声明了字符串指针,但是在你的for循环中,如果“if”不为真,那么它会转到其他地方,其中findPath永远不会指向任何东西而你试图在if(i == 1)

中访问它

<强>更新 还要考虑Lou Franco的回答。他也是对的。您没有拥有cloudList对象。它是自动释放的,你通过将释放消息传递给cloudList对象[cloudList release]来过度释放它。 在你的情况下,当你释放它时它可能不会立即崩溃,因为控制是在同一个循环中。一旦当前线程自动释放池耗尽,您的代码将因EXC_BAD_ACCESS而崩溃。

ASICloudFilesObjectRequest *cloudList = [ASICloudFilesObjectRequest listRequestWithContainer:containerName];
[cloudList startSynchronous];
NSArray *cloudFolderContents = [cloudList objects];
[cloudList release];// Remove this line 

<强> UPDATE2:

NSString *uploadPath=[[[NSString alloc] initWithString:@"~/Cloud Briefcase"] stringByExpandingTildeInPath];

将上述内容更改为

NSString *uploadPath=[[NSString stringWithFormat:@"~/Cloud Briefcase"] stringByExpandingTildeInPath];

上面一行中的uploadPath仍然指向自动释放的对象。您正在泄漏您创建的字符串。呼叫释放是错误的。因此,删除[uploadPath release]和[cloudList release],您将一次又一次地释放它。为什么你发布明显自动释放的对象uploadFolderContents?从代码中删除这三行:

[uploadPath release];

[cloudList release];
[uploadFolderContents release];

Update3:修复了过度发布问题。并且if中的updatePath更改为updatePathLocal,其中up​​datePath变量与方法范围存在冲突。

-(void)startUploadWithContainerName:(NSString *)containerName
{
//Make an object of NSFileManager and Fetch an array of local folder contents and cloud folder contents
NSFileManager *uploadManager=[[NSFileManager alloc] init];
NSString *uploadPath=[[NSString stringWithFormat:@"~/Cloud Briefcase"] stringByExpandingTildeInPath];
NSError *err = nil;
NSArray *uploadFolderContents=[uploadManager contentsOfDirectoryAtPath:uploadPath error:&err];
ASICloudFilesObjectRequest *cloudList = [ASICloudFilesObjectRequest listRequestWithContainer:containerName];
[cloudList startSynchronous];
NSArray *cloudFolderContents = [cloudList objects];

[uploadManager release];

NSLog(@"%lu",[uploadFolderContents count]);
NSLog(@"\n%@\n\n%@",cloudFolderContents,uploadFolderContents);
NSString *notFoundPath = nil;
NSString *foundPath = nil;
NSString *foundCloudMatch = nil;
NSDate *cloudUploadDate = nil;

for (int j=1; j<[uploadFolderContents count]; j++) {
    int i=0;
    for (int k=0; k<[cloudFolderContents count]; k++) {
        if ([[[cloudFolderContents objectAtIndex:k] name] isEqualToString:[uploadFolderContents objectAtIndex:j]]) {
            i=1;
            foundPath=[uploadFolderContents objectAtIndex:j];
            foundCloudMatch=[cloudFolderContents objectAtIndex:k];
            cloudUploadDate=[[cloudFolderContents objectAtIndex:k] lastModified];
            break;
        }
        else{
            i=0;
            notFoundPath=[uploadFolderContents objectAtIndex:j];
            continue;
        }
    }

    if (i==1) {
        NSLog(@"Found In Cloud: %@",foundPath);
        NSString *uploadPathLocal=[[NSString stringWithFormat:@"~/Cloud Briefcase/%@",foundPath] stringByExpandingTildeInPath];
        NSTimeZone *tCST=[NSTimeZone timeZoneWithAbbreviation:@"CST"];
        NSInteger cloudDifference=[tCST secondsFromGMTForDate:cloudUploadDate];

        NSFileManager *typeManager=[[NSFileManager alloc] init];
        NSError *Er = nil;
        NSDictionary *propertiesOfUploadFile=[typeManager attributesOfItemAtPath:uploadPathLocal error:&Er];

        NSDate *localUploadDate=[propertiesOfUploadFile objectForKey:NSFileModificationDate];

        NSInteger sourceUploadDifference=[[NSTimeZone systemTimeZone] secondsFromGMTForDate:localUploadDate];


        NSLog(@"Local Date %@",localUploadDate);
        NSLog(@"Local Difference %ld",sourceUploadDifference);
        NSTimeInterval diff=sourceUploadDifference-cloudDifference;
        NSTimeInterval sDiff=sourceUploadDifference;
        NSDate *lDate=[[NSDate alloc] initWithTimeInterval:sDiff sinceDate:localUploadDate];
        NSDate *comparisonDate=[[NSDate alloc] initWithTimeInterval:diff sinceDate:cloudUploadDate];
        NSLog(@"\nSDiff Value %@",lDate);
        NSLog(@"Comparison Date %@",comparisonDate);

        [typeManager release];

        if ([comparisonDate compare:lDate]==NSOrderedAscending) {
            [comparisonDate release];
            [lDate release];
            NSLog(@"Got It");
            NSString *escString=[foundPath stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
            ASICloudFilesObjectRequest *request = 
            [ASICloudFilesObjectRequest putObjectRequestWithContainer:containerName objectPath:escString contentType:@"file" file:uploadPath metadata:nil etag:nil];
            [request startSynchronous];
            NSLog(@"Uploaded %@",foundPath);
        }
    }
    else{
        NSLog(@"Not Found In Cloud: %@",notFoundPath);
        NSString *uploadPathLocal=[[NSString stringWithFormat:@"~/Cloud Briefcase/%@",notFoundPath] stringByExpandingTildeInPath];
        //          NSLog(@"%@",uploadPath);


        NSString *escString=[notFoundPath stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
        NSLog(@"URL ENCODED VALUE: %@",escString);

        ASICloudFilesObjectRequest *request = 
        [ASICloudFilesObjectRequest putObjectRequestWithContainer:containerName objectPath:escString contentType:@"file" file:uploadPathLocal metadata:nil etag:nil];
        [request startSynchronous];
        NSLog(@"Upload Complete");
    }
 }
}

答案 1 :(得分:1)

这一行:

[cloudList release];

是可疑的,因为你没有分配或保留cloudList - 它很可能作为autorelease返回,但是阅读了ASICloudFilesObjectRequest的文档。

即便如此,我认为这不是你的问题 - 一旦它被过度释放就会引起问题。

我看到许多版本看起来很糟糕 - 因为我没有看到相应的分配或保留。您需要阅读Objective-C的内存管理规则(或转移到自动引用计数)

我在这里记录了EXC_BAD_ACCESS的调试技术:

http://loufranco.com/blog/files/Understanding-EXC_BAD_ACCESS.html

轻松尝试:

  1. 运行构建和分析(修复所有内容)
  2. 打开僵尸

答案 2 :(得分:0)

也许,只是“findPath”可能没有设置为有效值。有一个调试器,也许你应该使用它。

答案 3 :(得分:0)

这可能是引用计数问题。

诊断:

  • 运行静态分析器
  • 修复所有静态分析器问题
  • 测试

在修复静态分析仪结果后仍有问题?没问题:

    在仪器中
  • ,您可以启用僵尸检测并记录分配历史记录和引用计数。
  • 运行您的应用,执行重现问题所需的步骤
  • 当收到僵尸消息时,仪器将暂停执行。
  • 然后找到已发送消息的分配/对象并逐步执行其生命周期/参考计数历史记录。

这使得定位过度释放的对象非常容易找到(例如,从某些情况下的几小时到几分钟)。