简体   繁体   中英

iPhone app crashes on device but not on simulator

I am having trouble with an application. It runs in the simulator, but when I try to run it on a device, it crashes. I tested it and it worked before submitting it to Apple for the review, but now, when I tried to take another look at it, it keeps crashing. Also, it doesn't crash right at the start, but when I try to navigate to a second view. Please let me know if you can help me to figure it out. Thanks!

(I have already tried setting NSZombieEnable, as I found this suggestion/answer in different posts but it does not work for me)

OS Version:      iPhone OS 5.1.1 (9B206)
Report Version:  104

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x6f466874
Crashed Thread:  0

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libobjc.A.dylib                 0x335b2f7e objc_msgSend + 22
1   Foundation                      0x34d24d04 _NSDescriptionWithLocaleFunc + 44
2   CoreFoundation                  0x3597496e __CFStringAppendFormatCore + 7998
3   CoreFoundation                  0x358ef1d8 _CFStringCreateWithFormatAndArgumentsAux                 + 68
4   Foundation                      0x34d24c2e +[NSString stringWithFormat:] + 54
5   Sustain                     0x00082148 +[HTMLParser parseDataForRequest:error:]     (HTMLParser.m:169)
6   Sustain                     0x00085a5a -[ProxyRequestResponseHandler     requestFinished:] (ProxyRequestResponseHandler.m:251)
7   CoreFoundation                  0x358f31f4 -[NSObject performSelector:withObject:] +     36
8   Sustain                     0x00054364 -[ASIHTTPRequest reportFinished]     (ASIHTTPRequest.m:2004)
9   CoreFoundation                  0x358f31f4 -[NSObject performSelector:withObject:] + 36
10  Foundation                      0x34dc3740 __NSThreadPerformPerform + 344
11  CoreFoundation                  0x35968acc __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 8
12  CoreFoundation                  0x35968298 __CFRunLoopDoSources0 + 208
13  CoreFoundation                  0x3596703e __CFRunLoopRun + 646
14  CoreFoundation                  0x358ea49e CFRunLoopRunSpecific + 294
15  CoreFoundation                  0x358ea366 CFRunLoopRunInMode + 98
16  GraphicsServices                0x33685432 GSEventRunModal + 130
17  UIKit                           0x330c2cce UIApplicationMain + 1074
18  Sustain                     0x00019c26 main (main.m:16)
19  Sustain                     0x00019bc0 start + 32
Thread 0 crashed with ARM Thread State:
    r0: 0x00128a98    r1: 0x325894f6      r2: 0x359eccd5      r3: 0x6f46687c
    r4: 0x32588417    r5: 0x00000000      r6: 0x3f3078c8      r7: 0x2fe0cb70
    r8: 0x2fe0cc13    r9: 0x0c96253d     r10: 0x359730b6     r11: 0x00000000
    ip: 0x3f2e26f0    sp: 0x2fe0cb5c      lr: 0x34d24d0b      pc: 0x335b2f7e
  cpsr: 0x200f0030

Here is the mathod you requested in HTMLParser

+ (BOOL)parseDataForRequest:(ASIHTTPRequest *)request error:(NSError **)error
{
NSStringEncoding encoding = [request responseEncoding];
NSString *string = [[NSString alloc] initWithContentsOfFile:[request downloadDestinationPath] usedEncoding:&encoding error:NULL];
[string release];
NSURL *baseURL = [request url];

xmlInitParser();
xmlDocPtr doc;
if ([request downloadDestinationPath]) {
    doc = htmlReadFile([[request downloadDestinationPath] cStringUsingEncoding:NSUTF8StringEncoding], [self encodingNameForStringEncoding:encoding], HTML_PARSE_RECOVER | HTML_PARSE_NONET | HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR);
} else {
    NSData *data = [request responseData];
    doc = htmlReadMemory([data bytes], (int)[data length], "", [self encodingNameForStringEncoding:encoding], HTML_PARSE_RECOVER | HTML_PARSE_NONET | HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR);
}
if (doc == NULL) {
    [super parseDataForRequest:request error:error];
    return YES;
}

// Create xpath evaluation context
xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
if(xpathCtx == NULL) {
    if (error) {
        *error = [NSError errorWithDomain:NetworkRequestErrorDomain code:101 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Error: unable to create new XPath context",NSLocalizedDescriptionKey,nil]];
    }
    return NO;
}

// Evaluate xpath expression
xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression(xpathExpr, xpathCtx);
if(xpathObj == NULL) {
    xmlXPathFreeContext(xpathCtx); 
    if (error) {
        *error = [NSError errorWithDomain:NetworkRequestErrorDomain code:101 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Error: unable to evaluate XPath expression!",NSLocalizedDescriptionKey,nil]];
    }
    return NO;
}

// Now loop through our matches
xmlNodeSetPtr nodes = xpathObj->nodesetval;

int size = (nodes) ? nodes->nodeNr : 0;
int i;
for(i = size - 1; i >= 0; i--) {
    assert(nodes->nodeTab[i]);
    NSString *parentName  = [NSString stringWithCString:(char *)nodes->nodeTab[i]->parent->name encoding:encoding];
    NSString *nodeName = [NSString stringWithCString:(char *)nodes->nodeTab[i]->name encoding:encoding];

    xmlChar *nodeValue = xmlNodeGetContent(nodes->nodeTab[i]);
    NSString *value = [NSString stringWithCString:(char *)nodeValue encoding:encoding];
    xmlFree(nodeValue);

    // Here we add a <base> element to the header to make the end result play better with javascript
    // (UIWebView seemed to ignore the Content-Base http header when I tried)
    if ([[nodeName lowercaseString] isEqualToString:@"head"]) {

        xmlNodePtr node = xmlNewNode(NULL, (xmlChar *)"base");

        xmlNewProp(node, (xmlChar *)"href", (xmlChar *)[[baseURL absoluteString] cStringUsingEncoding:encoding]);

        node = xmlDocCopyNode(node, doc, 1);
        xmlAddChild(nodes->nodeTab[i], node);

    // Our xpath query matched all <link> elements, but we're only interested in stylesheets
    // We do the work here rather than in the xPath query because the query is case-sensitive, and we want to match on 'stylesheet', 'StyleSHEEt' etc
    } else if ([[parentName lowercaseString] isEqualToString:@"link"]) {
        xmlChar *relAttribute = xmlGetNoNsProp(nodes->nodeTab[i]->parent,(xmlChar *)"rel");
        if (relAttribute) {
            NSString *rel = [NSString stringWithCString:(char *)relAttribute encoding:encoding];
            xmlFree(relAttribute);
            if ([[rel lowercaseString] isEqualToString:@"stylesheet"] || [[rel lowercaseString] isEqualToString:@"alternate stylesheet"]) {
                xmlNodeSetContent(nodes->nodeTab[i], (xmlChar *)[[self localURLForURL:value withBaseURL:baseURL] cStringUsingEncoding:encoding]);

            }
        }

    // Parse the content of <style> tags and style attributes to find external image urls or external css files
    } else if ([[nodeName lowercaseString] isEqualToString:@"style"]) {

        xmlNodeSetContent(nodes->nodeTab[i], (xmlChar *)[[CSSParser replaceURLsInCSSString:value withBaseURL:baseURL] cStringUsingEncoding:encoding]);

    // Parse the content of <source src=""> tags (HTML 5 audio + video)
    // We explictly disable the download of files with .webm, .ogv and .ogg extensions, since it's highly likely they won't be useful to us
    } else if ([[parentName lowercaseString] isEqualToString:@"source"] || [[parentName lowercaseString] isEqualToString:@"audio"]) {
        NSString *fileExtension = [[value pathExtension] lowercaseString];
        if (![fileExtension isEqualToString:@"ogg"] && ![fileExtension isEqualToString:@"ogv"] && ![fileExtension isEqualToString:@"webm"]) {
            xmlNodeSetContent(nodes->nodeTab[i], (xmlChar *)[[self localURLForURL:value withBaseURL:baseURL] cStringUsingEncoding:encoding]);

        }

        // For all other elements matched by our xpath query (except hyperlinks), add the content as an external url to fetch
    } else if (![[parentName lowercaseString] isEqualToString:@"a"]) {
        xmlNodeSetContent(nodes->nodeTab[i], (xmlChar *)[[self localURLForURL:value withBaseURL:baseURL] cStringUsingEncoding:encoding]);

    }
    if (nodes->nodeTab[i]->type != XML_NAMESPACE_DECL) {
        nodes->nodeTab[i] = NULL;
    }
}

xmlXPathFreeObject(xpathObj);
xmlXPathFreeContext(xpathCtx); 


// We'll use the xmlsave API so we can strip the xml declaration
xmlSaveCtxtPtr saveContext;


if ([request downloadDestinationPath]) {

    // Truncate the file first
    NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];

    [fileManager createFileAtPath:[request downloadDestinationPath] contents:nil attributes:nil];

    saveContext = xmlSaveToFd([[NSFileHandle fileHandleForWritingAtPath:[request downloadDestinationPath]] fileDescriptor],[self encodingNameForStringEncoding:NSUTF8StringEncoding],2|8); // 2 == XML_SAVE_NO_DECL, this isn't declared on Mac OS 10.5
    xmlSaveDoc(saveContext, doc);
    xmlSaveClose(saveContext);

} else {
    #if TARGET_OS_MAC && MAC_OS_X_VERSION_MAX_ALLOWED <= __MAC_10_5
    // xmlSaveToBuffer() is not implemented in the 10.5 version of libxml
    NSString *tempPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]];
    [[[[NSFileManager alloc] init] autorelease] createFileAtPath:tempPath contents:nil attributes:nil];
    saveContext = xmlSaveToFd([[NSFileHandle fileHandleForWritingAtPath:tempPath] fileDescriptor],[self encodingNameForStringEncoding:NSUTF8StringEncoding],2|8); // 2 == XML_SAVE_NO_DECL, this isn't declared on Mac OS 10.5
    xmlSaveDoc(saveContext, doc);
    xmlSaveClose(saveContext);
    [request setRawResponseData:[NSMutableData dataWithContentsOfFile:tempPath]];
    #else
    xmlBufferPtr buffer = xmlBufferCreate();
    saveContext = xmlSaveToBuffer(buffer,[self encodingNameForStringEncoding:NSUTF8StringEncoding],2|8); // 2 == XML_SAVE_NO_DECL, this isn't declared on Mac OS 10.5
    xmlSaveDoc(saveContext, doc);
    xmlSaveClose(saveContext);
    [request setRawResponseData:[[[NSMutableData alloc] initWithBytes:buffer->content length:buffer->use] autorelease]];
    xmlBufferFree(buffer);
    #endif

}
NSString *contentType = [[[request responseHeaders] objectForKey:@"Content-Type"] lowercaseString];
contentType = [[contentType componentsSeparatedByString:@";"] objectAtIndex:0];
if (!contentType) {
    contentType = @"text/html";
}

[[request responseHeaders] setValue:[NSString stringWithFormat:@"%@; charset=utf-8"] forKey:@"Content-Type"];
[request setResponseEncoding:NSUTF8StringEncoding];
xmlFreeDoc(doc);
doc = nil;

[super parseDataForRequest:request error:error];
return YES;
}

In the second view I load a webView that gets cached after being loaded. I used this project in order to obtain this: https://github.com/pokeb/ProxyingUIWebView What's weird is that it used to work, but now it doesn't anymore. I have tried to test it on another device and I get the same crash. This is what I have in my secondarry view controller:

-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString *urlString = [NSString stringWithFormat:@"%@", request.URL];

NSBundle *mainBundle = [NSBundle mainBundle];
NSString *baseUrl = [mainBundle objectForInfoDictionaryKey:@"testUrl"];

if ([urlString rangeOfString:baseUrl].location != NSNotFound)   //Check if URL is in-app.
{
    NSURLRequest *testRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://127.0.0.1:8080/?url=http.somelink.net"]];

    NSString *requestUrlString = [NSString stringWithFormat:@"%@",request.URL];
    NSString *testUrlString = [NSString stringWithFormat:@"%@",testRequest.URL];

    if ([requestUrlString isEqualToString:testUrlString])   //First view load
    {
        return YES;
    }

    if (navigationType == UIWebViewNavigationTypeLinkClicked ||
        navigationType == UIWebViewNavigationTypeFormSubmitted ||
        navigationType == UIWebViewNavigationTypeFormResubmitted ||
        navigationType == UIWebViewNavigationTypeReload ||
        navigationType == UIWebViewNavigationTypeOther)
    {
        if ([requestUrlString rangeOfString:@"Id="].location != NSNotFound) //Navigate to
        {                                                                   //secondary view.
            SecondaryTopTenSwapsViewController *secondaryController = [[SecondaryTopTenSwapsViewController alloc] init];
            secondaryController.urlRequest = request;
            [self.navigationController pushViewController:secondaryController animated:YES]; 
        }
        return NO;
    }

    return YES;

}
else    //Not in-app URL. Check if user wants to leave application and open Safari.
{
    UIAlertView *leaveApplicationAlert = [[UIAlertView alloc] initWithTitle:@"Open link?" message:@"Are you sure you want to exit the application and open the link in Safari?" delegate:self cancelButtonTitle:@"NO" otherButtonTitles:@"YES", nil];
    leaveApplicationAlert.tag = 1;
    [leaveApplicationAlert show];
    externalUrl = request.URL;
    return NO;
}
}

Also, I found that in my secondary view controller it crashes right after

-(void)webViewDidStartLoad:(UIWebView *)webView

Also, it can't be a memory issue, as if I receive a memory warning, I pop to the root view controller and release all the subviews.

You are trying to access an object by casting it's format type incorrectly.

For example, you are trying to access an integer value by using the format type %@ rather than %i or %d .

NSInteger someInteger = 255;
NSString *string = [NSString stringWithFormat:@"Hello, my favourite number is %@", someInteger"];

If you post some code, I can outline where this is occurring.

From your stack trace, it looks like the string where the issue is arising is being passed into a method where the HTMLParser object is the receiver.

Edit---

Another possibility is that one of the arguments passed to the NSString has already been released and cannot be accessed as it has been deallocated and furthermore removed from memory.

Edit----

I believe that the problem is on this line:

[[request responseHeaders] setValue:[NSString stringWithFormat:@"%@; charset=utf-8"] forKey:@"Content-Type"];

You use the format string %@ , yet do not provide an NSString as an argument.

I believe that you meant to code the following:

[[request responseHeaders] setValue:[NSString stringWithFormat:@"%@; charset=utf-8", contentType] forKey:@"Content-Type"];

Turn on Zombies and Malloc Scribble (scheme diagnostics) and debug your app (either simulator or device or both). Likely you have a deallocated object you are working with. Random memory accesses may succeed or fail when you read (or write) via a deallocated object or pointer. That's the most common reason for such inconsistent behavior.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM