I have a situation in my renderer where I load some DLLs and perform some validation within them. When the validation fails, I throw an exception from the DLL to exit the renderer with a MessageBox detailing the error, and also logging the error to a file. Because of funkyness with throwing exceptions across DLLs, in order for Windows not to terminate the EXE, I purposely leak some std::unique_ptr objects by doing obj.release(), when the renderer is exiting via an exception. The idea is that, since we're exiting via an exceptional circumstance, the leaking of these objects is acceptable because the OS will cleanup the memory at app exit.
I'm running into a problem with AMD's Vulkan Memory Allocator. The allocator does an assertion check to make sure all its memory has been freed. Since I'm purposely leaking the memory, in this case, I don't want that assertion to trigger.
Is there a way to manually release the VMA memory such that this assertion is not triggered? Since I leaked the objects that point that memory, I can't release the memory on a per object basis.
I wish VMA would have a way to disable those assertions at runtime.
NOTE: This is all happening during development, in Debug mode. For now, Release mode is not a concern.
Related
Is there a way to prevent an EXC_BAD_ACCESS from crashing an app, like with #try..#catch you can handle an exception gracefully.
Update:
The code crashes when it attempts to dereference an invalid pointer. This is a third party library and it interfaces with external hardware so I can't debug locally. I am trying to prevent it from crashing and output data to a debugging console on my app.
In ObjC, try/catch do not handle exceptions particularly gracefully. You will still leak memory and leave the system in an undefined state. With rare exception, the expectation is that you are simply catching so you can log some things before crashing. And in general, you should not use #catch anywhere but at the top level of your program for this purpose. There are some extraordinary situations where limited use of exceptions may be appropriate, but they are rare in ObjC. See the Exception Programming Guide for some more information. See especially the following from the ObjC ARC documentation:
The standard Cocoa convention is that exceptions signal programmer error and are not intended to be recovered from. Making code exceptions-safe by default would impose severe runtime and code size penalties on code that typically does not actually care about exceptions safety. Therefore, ARC-generated code leaks by default on exceptions, which is just fine if the process is going to be immediately terminated anyway. Programs which do care about recovering from exceptions should enable the option [-fobjc-arc-exceptions, which imposes speed and memory penalties on your program].
The same is true of EXC_BAD_ACCESS. You can catch it with a signal handler for the purpose of recording some information and then finishing your crash. For a good tool for doing this see PLCrashReporter. It is very difficult to write such a handler correctly, so I strongly recommend using an existing framework. You can easily get into deadlocks that drain the user's battery if you catch EXC_BAD_ACCESS incorrectly.
You get EXC_BAD_ACCESS often because you sent a message to a released object. Then you can examine the NSZombie. What is an NSZombie? You can see : this. It will catch the
EXC_BAD_ACCESS because of sent a message to the released object.
You can set NSZombie like this : Check the Enable Zombie Objects
And you can also get EXC_BAD_ACCESS because of the memory warnings level is too high , or your memory is too high , so the apple will shut your app down. This EXC_BAD_ACCESS is too hard to prevent . I think the only way is to manage your memory as low as you can , sometimes you can see the log where is receive memory warning , when the level is high, it may getEXC_BAD_ACCESS
You can rewrite your code to not have these errors. Try not to reference any null pointers and keep references to any object that you want to have access to.
I am using Garbage collector in my Cocoa based application on Mac OS X. It has 100s of threads running and synchronization is done using Operation Queue.
After a long run, one of the object is garbaged and application will crash.
Checking to see if the object is non nil also fails as the the object is invalid and contains some garbage value. Calling a method on the object leads to crash.
Anyone please help me in debugging the issue.
Thank you......................
I am using Garbage collector in my
Cocoa based application on Mac OS X.
It has 100s of threads running and
synchronization is done using
Operation Queue.
More likely than not, the bug lies within the seemingly rather overly concurrent nature of your code. Running 100s of threads on a machine with "only" double digits worth of cores (if that) is unlikely to be very efficient and, of course, keeping everything properly in sync is going to be rather difficult.
The best place to start is to turn on Malloc stack logging and use malloc_history to find out what events occurred at the address that went south.
Also, there were fixes in 10.6.5 that impacted GC correctness.
If you can change the code of the garbage collected object, then override the finalize method like this, to get some information:
- (void) finalize
{
NSLog(#"Finalizing!\n%#", [[NSThread callStackSymbols] componentsJoinedByString:#"\n"]);
//if you put here a breakpoint, you can check the supposed references to this object
[super finalize];
}
I am really interested to know that, Is it possible that using try ... catch mechanism, we can avoid memory crash of our application ... ??
Let say the program part that we are expecting a chance of memory leak is kept under try...catch block, if the program crashes (ie memory leak) occurs then catch statement execute. So we can prevent our program from being crashed.
Is it possible ? If yes, How Or If not , why not ??
A try/catch block is there to catch an exception and stop it from propagating upwards in your callstack.
The idea goes that you catch it at the place where you know how to handle it, and then you get a chance to execute code in response to the exception.
It is not a magical solution that will prevent anything, it is just what I said above. What you do with the exception is what matters.
And a memory leak and a crash is not the same thing, it is rare that a program crashes due to memory leaks, unless it actually runs out of memory. A memory leak is rarely "fixable" after the fact. The correct, and usually only, way to fix a memory leak is to avoid it happening in the first place.
Also, yes, in a way you can keep your program from crashing by adding try/catch blocks all over, but the only thing you've succeeded in is to hide the crash from the user, and then let the program continue running. "Crashes" are not always safe to ignore, or rather, they are usually not safe to ignore.
If you are looking for some catch-all advice on how to avoid a program crashing, here's my advice:
Write a program that works correctly
I think we need to know more about what kinds of problems you're having, or you need to post a clearer question.
I would not trust any in process system to do the right thing in case of an out of memory condition. We have systems which completely lock up when a PermGen exception occurs and need a kill -9 to get rid off.
If you want the system to self correct, wrap it in a script or a system which monitors the health, a heart beat or a diagnostics page or whatever makes sense. If you receive no health indication kill it (hard if necessary) and restart it.
Best of all is to use testing and validation to include monitoring the memory (and disk) usage and make sure you really know how your system behaves and is properly configured so it does not happen.
The restarting solution is a poor alternative, because you then must test and ascertain that you can kill your application at any time and be confident it can be restarted correctly, which might even be more difficult.
If you are asking "can I catch segmentation faults with try catch", the answer is no.
try catch is for handling Objective-C exceptions i.e. those raised by executing an #throw statement. Segmentation faults caused by e.g. null pointer dereferences are generated by the operating system and are examples of Unix signals and can only be caught and handled by OS level system calls e.g. the sigaction(2) system call. Even then, the only sane thing you can do is terminate the program immediately because you might have a corrupt heap or stack.
I am just getting started again with Mac development.
I am using CoreMIDI which is a C API which allows me to define a C callback function to be called from the MIDI server on a separate thread whenever a MIDI message arrives. The registration of this callback is done in Objective-C/C code triggered by an awakeFromNib call.
It seems to work fine, except when I get my first callback I get the following warning message on the console:
MidiList(6685,0x103ddb000) malloc: *** auto malloc[6685]: error: GC operation on unregistered thread. Thread registered implicitly. Break on auto_zone_thread_registration_error() to debug.
I read up on this online and it sounds like a harmless error. But the weird thing to me is I don't understand how a "GC operation" occurred? My project does have GC enabled, but I thought that was only for the Cocoa parts. And my callback doesn't use any Cocoa code, it is just a free function which uses some CoreMIDI and CoreFoundation functionality (including CFSTR if that matters). Why would a GC operation occur on that thread if i'm not using any Cocoa objects?
Because the garbage collector doesn't know you're not using Cocoa on this thread.
The garbage collector that Cocoa sports is a conservative garbage collector: it actually knows next to nothing about how your program is structured. All it does is scanning the stack of each thread, and objects on the heap, for bit patterns that look like pointers, and if there's an object at this would-be location, it keeps it alive.
There is, obviously, a possibility for false positives. You can have an integer that has a value looking like a pointer and the garbage collector will believe it's one.
Besides, you may allocate garbage-collected memory in a malloc-like way with NSAllocateCollectable. The GC must take them into account too, especially since the returned pointer could be passed into C code that's not even aware of garbage collection.
EDIT Aside from NSAllocateCollectable, Core Foundation objects (CF-prefixed types) can be made garbage-collected with the help of CFMakeCollectable. Once it's used, the garbage collector will take care of them.
If you are creating pthread, add this objc_registerThreadWithCollector(); to your pthread.
In case you cannot find a symbol or linking error, use following code,
#include <dlfcn.h>
void (*registerThreadWithCollector_fn)(void);
registerThreadWithCollector_fn = (void(*)(void)) dlsym(RTLD_NEXT, "objc_registerThreadWithCollector");
if (registerThreadWithCollector_fn) {
(*registerThreadWithCollector_fn)();
} else {
// do something else
}
As the title says, my app crashes when garbage collection is not enabled. The app pops up for a few seconds and then it just crashes, with nothing but this in the debugger console:
[Session started at 2009-08-17 15:03:20 -0600.]
GNU gdb 6.3.50-20050815 (Apple version gdb-966) (Tue Mar 10 02:43:13 UTC 2009)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-apple-darwin".sharedlibrary apply-load-rules all
Attaching to process 12535.
unable to read unknown load command 0x22
unable to read unknown load command 0x22
unable to read unknown load command 0x22
unable to read unknown load command 0x22
I don't know why its happening. I think its probably a memory management issue. I used AnalysisTool (front-end to Clang Static Analyzer) to check for leaks and memory management issues, and I fixed the issues it found. Running the app through Instruments however reveals a memory leak around the time it starts. I have no idea where this leak is coming from...With garbage collection enabled the app runs fine, but Instruments still finds a leak.
Source code is available upon request
Thanks
Since the error says it occurs when calling [CFArray countByEnumeratingWithState:objects:count:] on a deallocated object, that gives you a fairly good idea of where to look. That method is part of part of NSFastEnumeration, so unless you're calling that method directly (highly unlikely), it is being invoked from within a for (... in ...) loop on your array object. If you can figure out where that is, you can set a breakpoint on (or just before) the for loop and check whether your object has been deallocated. The most likely cause of the problem is failing to properly retain the array, and it is probably released by the run loop draining an NSAutoReleasePool.
XCode has a bunch of memory profiling support built in - turning those on might reveal more information. I found these links particularly helpful:
http://developer.apple.com/technotes/tn2004/tn2124.html#SECMALLOC
http://www.cocoadev.com/index.pl?NSZombieEnabled
http://www.cocoadev.com/index.pl?DebuggingTechniques
http://www.cocoadev.com/index.pl?DebuggingAutorelease
You're probably releasing an object when you shouldn't, then sending it a subsequent message. unfortunately, the crash (where the subsequent message is sent) isn't where the problem is - it's where you are releasing (or worse, deallocing) where you shouldn't. The clang static analyser isn't foolproof, and blindingly following the advice won't necessarily have helped.
If it crashes after showing something for a few seconds, it may indicate that something that needed to be retained was released by the autorelease pool at the end of the run loop. Have a look at places where you assign variables with objects returned by other methods. Any method without "new", "copy", "alloc" (there's a few others I think) in the name usually indicates that you'll need to retain it if you want to keep using it.
It could also mean that you have released something that you shouldn't have and it was released again by the autorelease pool. Have a look at all the places you are releasing objects and make sure that you are only releasing objects that you have either retained yourself, or releasing objects returned by methods that explicitly state ownership, such as "new", "alloc", "copy", "mutableCopy" and so on.