In Racket, is there a way to safely catch and handle out-of-memory errors without terminating the program?
Related
I noticed when I run a big job in my grails application (that reads huge amounts of data from db) I have this log(no idea what generates the log, maybe the melody plugin?): Memory usage: used=588MB free=14MB total=683MB in the console and soon I receive:
Exception in thread "http-nio-8180-AsyncTimeout" Exception in thread "http-nio-8180-ClientPoller-1" Exception in thread "Thread-11" java.lang.OutOfMemoryError: GC overhead limit exceeded,
even though the heap memory seems to have much more memory left as displayed in intellij:
.
Also, starting the application I explicitly added JVM params:-Xmx40968m -Xms2048m.
On what type of memory do I run low?
It's not duplicate. My question is how to symbolicate crash error.
My live app is crashing and I've crash report in xCode and crashlytics but I don't have crashlog as it's happening on live app and it's random.
Is it possible to get some meaning out of crash report without a crash log?
How do we find out file & line number from such reports?
Here is one example of such crash
crash_info_entry_0
abort() called
crash_info_entry_1
myapp(569,0x16df57000) malloc: *** error for object 0x10404ddae: pointer being freed was not allocated
Symbolication is the process of translating addresses into symbols (functions, methods, etc). Without a crash log, which contains those addresses, symbolication doesn't make sense. You cannot translate addresses you do not have. But, where did the output you listed come from? It looks like it could be part of a larger log. You've tagged the issue Crashlytics - did this report come from their service?
There's some helpful information in the logging you've included. The good news is that it is telling you that you've got heap corruption. malloc has called abort because it's detected an inconsistency with its internal structures. Further, it's extremely unlikely that a symbolicated stack trace would help you, because heap corruption is rarely, if ever, caused by functions further up the stack.
Keep in mind that the crash you are seeing here is an effect. To fix this issue, you need a cause, and a stack trace isn't going to get you that in this situation.
There's more bad news. It is hard, and often even impossible, to reason about heap corruption. Replicating the bug can also be impossible, as memory corruption is typically not deterministic. As you've noted, the crash appears random. That's because it probably is.
What I would recommend doing here is using the various tools that Apple provides to help debug this kind of issue.
Look for other crashes that look heap-corruption-related
Try out Zombies in Instruments
Try malloc scribble, or guardmalloc, two other good memory debugging tools
It is extremely common for one heap-corrupting bug to cause lots of different kinds of crashes. This could be an objc over-release, so I'd also keep my eye out for selectorNotRecognized exceptions. Those crashes might give you more of a clue as to what kind of object is being over-released.
Good luck!
EXC_BAD_ACCESS is a trouble but it does improve the newbie experience regarding memory. I am a C programer improvising to iOS development.
What is EXC_BAD_ACCESS concept in terms of memory ?
Why it can't be caught in catch block, Is it not a run time exception though it incur at run time.?
EXC_BAD_ACCESS occurs when something that caused a pointer (yours, one internal to the iPhone, or one that the allocator is using) to be dereferenced and that memory location isn’t inside one of the chunks assigned to your program.
This could be because
The pointer used to point to memory that was ok, but its chunk was deallocated.
The pointer is corrupt.
And try-catch style exceptions are non-recoverable in iOS/Cocoa. Exceptions are not to be used for recoverable error handling . Check this one Is there a way to catch or handle EXC_BAD_ACCESS?.
I have simple code that executes and in case it crashes I want to catch the exception so the app does not crash.
#try {
x = [self try_doMyWork:Param];
} #catch (NSException* e) {
NSLog(#"Exception");
}
While this code works in debug and catches the exception (which is a simple index beyond end of array) it crashes in distributed apps on iPhones.
Why is this and how can I ensure that it also works on distributed apps?
Uncaught application-level exceptions are only one cause of crashes. BSD signals, like EXC_BAD_ACCESS, can also cause crashes - and catching NSExceptions won't prevent those.
It's impossible to say what the specific crash is without knowing the details of try_doMyWork:, but I think the most common cause of crashes in the C layer (not the Objective-C layer) is memory management problems - an attempt at writing or reading something your app is not supposed to access. The most likely explanation is that the exception you see in debug is not the same as the error you see in distribution.
In debug mode, the heap manager may allocate objects with buffer zones before and after them (called guards) and fill those guards with known values (like 0x7F). It does this so that it can test those guards when you release the memory and it can tell if you wrote beyond the end of the allocated memory (or before the start of it). In this way it can advise you that your code has a bug (a memory scribbler).
In release mode, it does not create these guards and so when you write outside of the allocated memory, bad things (like crashes) happen.
Does it make sense to continue execution after catching EOutOfMemory exception or now heap or stack is corrupted with a high probability?
I don't mean the case of EOutOfMemory caused by previous memory corruption due to bugs like writing to a wild address, I mean correct code that calls GetMem and catches EOutOfMemory.
In my opinion, there's no point attempting to continue from EOutOfMemory. In my experience, chances are exceedingly high that the heap will be corrupted and future errors can be expected. Usually, the safest course of action is to terminate the process.
In general, I agree that there's no point trying to recover. But it can be useful in specific circumstances. For example, allocating large amounts of memory that depend on user choices, and if it fails you can back out cleanly and let them retry with different settings. I do this for converting point clouds to 3D meshes, which includes some steps where the memory requirements aren't known in advance. It just takes careful coding of the steps you want to be recoverable, with an immediate and clean backout path. For example, some of my data structures are bitmaps or buffers with each line allocated separately to minimize issues with fragmented memory. The constructors have try... except handling and throw an EOutOfMemory exception, and the destructors free any of the lines that were already allocated. I can't guarantee it will always work, but it has worked well enough to be worth doing.