CGContextDrawPDFPage crashing without ever producing a memory warning
Asked Answered
W

2

2

I'm trying to render a PDF page with some annotations on it (to email), and most of the time this works fine.

However, with this PDF in particular it seems to crash every time on the call to CGContextDrawPDFPage for the first page. I have added

CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
CGContextSetRenderingIntent(context, kCGRenderingIntentDefault);

as a recommendation from CGContextDrawPDFPage taking up large amounts of memory but that did not seem to solve my issue.

I ran this through the profiler to see what was going on, and it slowly started allocating a bunch of memory until finally it hit 512MB of live bytes and died. memory allocation profiled in instrument

The strange thing is that when I render this to an image (for display on the device) context it seems to work fine but when I render it to a PDF context (for emailing with annotations), it breaks. All of the other PDFs I've tried work fine in both cases.

I was hoping that someone who's written a PDF viewer/annotator could test this out and see if this document works for them and if so, give me some tips about what they're doing to reduce the memory allocations of CGContextDrawPDFPage.

Another resource I looked at was this great SO Question.

Edit (more info on the crash):

90% of the time the crash doesn't actually show up, the gdb line displays but the app goes away and the stack trace doesn't show. (It says paused but there is no thread display). One time I saw it was an exc_bad_access and it showed this in the log:

malloc: *** mmap(size=16777216) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
Westwardly answered 29/2, 2012 at 17:35 Comment(1)
I've added an edit about the crash.Westwardly
C
1

Are you constructing the PDF on the main thread? If so, you may not receive the memory warning because you've blocked the signal while in execution, since the run loop never has a chance to dispatch the message to you.

Cambyses answered 29/2, 2012 at 20:14 Comment(10)
Yeah right now it's on the main thread. If I were to thread this and receive the warning, what could I do to solve the issue though since just a single call causes the memory to be used up?Westwardly
@PhilippeSabourin I looked at the PDF in Instruments on 10.6.8. Either something is very wrong with the PDF's drawing, or with the system frameworks. Including thumbnails, opening the file in Preview required over 10 GB total - it was creating a ton of images (perhaps from vector graphics?). I can't make enough sense of the raw PDF file format to see what's up, nor do I have a good PDF editor to see what is up with this file (unless it is some unusual issue in CGPDF implementations). The problem is not in your implementation =)Cambyses
@PhilippeSabourin If you are the creator of the file, then try to reduce that effect, but I'd also recommend filing a bug with Apple on this one.Cambyses
As I understand it, he is rendering, not constructing, the PDF.Valrievalry
Yeah this was not a PDF we created, just one someone used to test our app. You can import the PDF and then draw on it and email it back out as a PDF with annotations on it.Westwardly
@PhilippeSabourin and David yup - I threw that out just in case, but I did not assume that was the case. Perhaps an alternative PDF renderer would not have the same issue, if you need to support this case.Cambyses
So I've threaded the rendering of the PDF but I'm having trouble with how I can handle the memory warning, as in this case it comes up during the call to CGContextDrawPDFPage(context, page); so it's not like i can check isCancelled on the NSOperation and stop rendering. By the time this call comes back it will have crashed. Any ideas?Westwardly
@PhilippeSabourin a) file a bug with apple b) perhaps there is a third party pdf renderer you can use in your app c) or try to determine what about the file causes this (you'd need to know a bit about the document format) d) record open file status to disk -- if you do crash, present an alert on relaunch. there's no means i know of to cleanly cancel CG-rendering here on ios. sorry :(Cambyses
I'm going to mark this as the answer since there doesn't seem to be a real answer, threading and bug to apple seems to be the best solution.Westwardly
alright. there are third party libs -- here's one: pspdfkit.com. even if you find a third party lib that uses the same CG-APIs that fail, it may provide parse support - if you would like to go as far as using its parser to detect potential problems before it consumes all your memory.Cambyses
D
-1

Remove the exception breakpoint in xcode and it works fine.

Dermott answered 5/1, 2016 at 10:31 Comment(1)
This would crash in release mode with out of memory errors, not sure what removing a breakpoint would help.Westwardly

© 2022 - 2024 — McMap. All rights reserved.