Memory issue with large NSData - ios

I was reading a really large file into memory on the main thread (not just the simple dataWithContentsOfFile: method, I was also doing some data manipulation), and my app crashed. After I moved this process to a background thread, the app doesn't crash anymore. The only thing that happens is that the NSData I get is nil.
Is it possible that only my background thread is interrupted without affecting the main thread, or am I missing something? Also, can I count on this behaviour and just display an error message when the NSData is nil, without the app to crash? Thank you in advance.
Edit:
The log I get is:
malloc: * mmap(size=629800960) failed (error code=12)
error: can't allocate region
** set a breakpoint in malloc_error_break to debug
The file I was using is about 250 MB large.
I know why it crashed on the main thread. My question is, why didn't it crash on a secondary thread?

I guess it can depend on the crash, but if it is a problem of lack of memory (you can both be using too much memory or be creating too many objects) it will crash the entire app.
You should try to test the app with smaller files and see how it behaves.

Related

Does iOS Instruments miss thread stack deallocations, or is this leak real?

At launch our app starts a large number of threads to asynchronously load files, thus:
if( !pthread_create( &_handle,0,run,this ) ){ pthread_detach( _handle ); }
According to XCode, all these threads complete and disappear. However, according to the Allocations instrument, 50mb of VM:Stack remains allocated, with only a handful of the file-loader thread stacks being deallocated.
If I replace pthread_detach with pthread_join, Allocations reports the stack memory as deallocated correctly.
This behaviour manifests in XCode 11.3.1 when allocating around a hundred threads in rapid succession on a device running iOS 12.1.4 using the code above.
I need to know whether the failure is with the instrument, or in the threading itself. I suspect the former but have been unable to prove that to my own satisfaction.

Objective-C - How to force low memory on iOS simulator

I have an error that some users are having of EXC_BAD_ACCESS when their device is low on memory. The stack trace is pointing to the if line below, and I believe it's because of the UTF8String that's being deallocated and still being used:
dispatch_sync(dbQueue, ^{
if (sqlite3_bind_text(sql_stmt, 1, pid.UTF8String, -1, SQLITE_STATIC) != SQLITE_OK) {
...
I'm having a hard time reproducing the issue on my end, how can I force or simulate low-memory on the simulator or a device?
Update:
I've tried adding a breakpoint to the line above, and then using the option Simulator -> Simulate Memory Warning, but I still can't reproduce the EXC_BAD_ACCESS error.
In the simulator there is a menu item: Hardware : Simulate Memory Warning
or
shiftcommandM
In simulator's menu: Hardware-> Simulate Memory Warning.
Update
If you're sure that your app crashed at sqlite3_bind_text, I suppose the most potential problem could be that the pid.UTF8String is NULL sometimes in which case it causes crash. Additionally, it's not likely to be the case that pid or pid.UTF8String is deallocated when used, you can check the crash report (if you have any) and check the address of the memory which caused the EXC_BAD_ACCESS, for example if you have EXC_BAD_ACCESS CODE=2 ADDRESS=0x00000000, it means pid.UTF8String is indeed a NULL pointer, if the address is not 0x0, then, it's another problem (very unlikely in your case).
As a suggestion, please add nil check to your code:
if (pid) {
if (sqlite3_bind_text(sql_stmt, 1, pid.UTF8String, -1, SQLITE_STATIC) != SQLITE_OK){
// do your stuff
}
} else {
sqlite3_bind_null(sql_stmt,1);
}
Many times, these kinds of errors are the result of a "perfect storm" of circumstances (i.e. race conditions, infrequent tasks running at just the "right" time, etc.), and often the kind of circumstances that you just cannot anticipate; if you knew how to reproduce it reliably, you'd probably also know how to fix it. The next best thing you can hope for is to try and increase your statistical odds of reproducing it in an environment (the debugger) where you could hopefully make sense of what's happening.
See this post: iOS Development: How can I induce low memory warnings on device?. By simulating memory warnings programmatically, you can (for example) use a repeating timer to cause a memory warning 1/sec (much faster than that and you may run into other issues, which will have you chasing your tail more than solving your original problem), eliminating the need to do it by hand repeatedly.
Before actually running the test, you can also set breakpoints at the following locations:
Symbol Module
====== ======
objc_exception_throw libobjc.A.dylib
-[NSException raise] CoreFoundation
Additionally, set breakpoints on all Objective-C exceptions. Setting a breakpoint will allow you to inspect the contents of memory before the exception actually gets thrown by the runtime, which will give you a much better chance of understanding the problem when it happens. When (and if) you capture the crash, inspect pid, pid.UTF8String and sql_stmt, as those look like the most likely culprits.
Run your app and start the timer firing. This will not necessarily or directly cause the crash you're looking for, but it will probably make it much more likely to occur over time without having to hand-hold; you can fire off the timer and wait (i.e. do something more productive) until you actually see the crash.
On the left side of your Xcode screen you can see a button to open the Debug Navigator, there you can see the amount of memory your app is currently using, and the amount that is free.
If you analyze it, you'll realize that the available memory for your simulator is the same as from your computer, so I suggest that you run some application that uses a lot of memory simultaneously with the simulator.
If you have an iPad available it might be easier, what I usually do is go on this website and copy as much of the unicode table as possible, so it will be stored on the Pasteboard

how to load more cells in tableView

i am writing a iPad application and displaying the tableView in my application. I have two options in tableview:
includeAll
ExcludeAll
Once i click the IncludeAll all cells should be selected. I am loading more then 10000 records. once i select the include all i got one error message.
error message is
malloc: *** mmap(size=2097152) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
Googling will reveal quite a few tutorials on using instruments to understand what is going on with your memory:
How to debug memory leaks: (tutorial)
http://www.raywenderlich.com/2696/how-to-debug-memory-leaks-with-xcode-and-instruments-tutorial
And another:
Finding Obj-C memory leaks (video)
http://www.youtube.com/watch?v=R449qEuexNs&feature=related
Probably because your simulator is able to allocate ~500Mb of memory while your iPad is not able to do it. I think you should rethink what you are doing
do you really need so much memory?
isn't it just a calculating bug? (maybe a wrong sizeof or whatever)
in any case this is really too much data to be handled

"Received memory warning" when using NSThread in ios

I am developing iPhone App. i am using NSThread for continuous calling of function which contains C++ code.
when i use NSThread or dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
Function calling
}
then it gives me "Received memory warning" warning after 5min and crash the application.
but when i run this function on main thread/Queue then it works perfactly.
also i have tried Xcode profiler for check memory leaks but no memory leaks found.
how can i resolve this issue?
thanks in advance.
Instruments may not see all memory leaks especially if you are calling some C code as you are by passing the retaining functions.
It's hard to give you an answer without knowing what your thread contains but you may want to check your code for unreleased object / mis-deallocated / destroyed objects.
You should also check that you are not creating a whole bunch of threads (NSThread) and that they are correctly releasing their contents after termination.
By the way, your app shouldn't terminate when receiving a memory warning, it's a normal message coming from the OS. Check your deallocation when viewWillUnload / didReceivedMemoryWarning functions are called.
You should also try to create memory warning manually using the simulator
I had a somewhat similar problem using a NSOperationQueue on a background thread.
Assuming you have already declared you mandatory NSAutoreleasePool in the function, you could try to allocate/release the objects yourself and don't use autorelease unless necessary, to make sure the memory is freed right on time.
A second advice would be to use Instruments and Allocations, to see what exactly takes up your memory. Probably you have some object being retained and not released when it should be. This post is AMAZING when it comes to this http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/ and you might also find some useful info here http://www.cimgf.com/2008/04/02/cocoa-tutorial-fixing-memory-leaks-with-instruments/
Otherwise... you need to post more details.
Good luck!

CGContextDrawPDFPage crashing without ever producing a memory warning

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.
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
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.
Remove the exception breakpoint in xcode and it works fine.

Resources