Reputation: 1143
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.
Upvotes: 1
Views: 3757
Reputation: 2584
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.
Upvotes: 0
Reputation: 24481
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"];
Upvotes: 4