Due to seeing random memory crashes in my iOS program, I decided to use Valgrind to help root out the problem, as they have a port that runs on the 32-bit mac OS X. I followed the instructions in this web page to set up Valgrind on the iPhone simulator here:
http://landonf.bikemonkey.org/code/iphone/iPhone_Simulator_Valgrind.20081224.html
However, although I can get the program to compile in the iOS simulator, and the pre开发者_如何转开发processor flags set, I could not get Valgrind to actually run my program. It always quits with the following error:
valgrind: /Users/megahub/Library/Application Support/iPhone Simulator/4.2/Applications/6FD1FFF3-0EFB-4D81-A95A-F02E0AA9095E/QuamStockAdHoc.app/QuamStockAdHoc: cannot execute binary file
cannot execute binary file
How can I resolve this problem? I've verified that the executable is present at that path, because I can run it without Valgrind in the simulator.
The compiler default is 64-bit (assuming you have a 64-bit machine), but valgrind does not yet officially support 64-bit executables on Mac OS X,(As per my knowledge, I might be wrong). The file command on your executable should report "Mach-O executable i386". Also be sure that you have 32-bit versions of all the libraries you are using.
There may be other things that trigger this message, but a common cause is trying to use valgrind on a 32 bit executable when it has been compiled to only run on 64 bit executables. (MacPorts as of this writing does that on 64 bit OS builds). This isn't specific to the simulator: trying to valgrind any 32 bit app will produce this.
A native install from source of valgrind with no extra arguments to configure
will work on either 32 or 64 bit executables.
This doesn't get me all the way to being able to run valgrind within the simulator. Not yet ...
Follow up:
Getting the width right doesn't get you too far. As mentioned somewhere else, what's really required is porting valgrind to the simulator runtime. It needs to use all the platform SDKs just like the target app does.
Turns out, this is possible. Not easy, and I'm not sure how stable it is, but possible. I think I'll talk to the valgrind folks about whether this can be cleaned up somehow and made a supported port/target.
When it works, it's beautiful:
char* p = new char[10];
delete p;
*p = 12;
turns into
==49084== Invalid write of size 1
==49084== at 0x6C536: -[AppDelegate application:didFinishLaunchingWithOptions:] (app_delegate.mm:813)
==49084== ...
==49084== Address 0xc6cca70 is 0 bytes inside a block of size 10 free'd
==49084== at 0xC51041: free (vg_replace_malloc.c:430)
==49084== by 0x6C52F: -[AppDelegate application:didFinishLaunchingWithOptions:] (app_delegate.mm:812)
==49084== ...
Pretty symbols and line numbers. Wonderful.
Status:
I got to the point where valgrind would barf on Apple's sqlite3 dylib. I'm not 100% sure why but I think it's because Apple's version of sqlite3 has some mach calls that valgrind doesn't cover. So I never got it to work in total on my app. I raised the topic on the valgrind list but it didn't raise any interest. I'd still like to get it to work, but it's not going to happen too soon ... at least not by me.
Hmmm ... wonder if I can raise any interest at WWDC ...
Why use valgrind in the first place? You have NSZombie and friends plus Instruments with its leak checker.
How to set up:
- Go to Xcode, select your built product (the .app), doubleclick on that. (in Xcode 4 Menubar->Product->Edit Scheme)
- Add a new environment variable named "NSZombieEnabled" and set the value to "YES"
Alternatively for more control:
Create a new file in your home directory named ".gdbinit" (note the dot in front) with the following content:
fb -[NSException raise]
fb -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:]
fb -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:]
set env MallocHelp=YES
set env NSZombieEnabled=YES
set env NSDeallocateZombies=NO
set env MallocCheckHeapEach=100000
set env MallocCheckHeapStart=100000
set env MallocScribble=YES
set env MallocGuardEdges=YES
set env MallocCheckHeapAbort=1
set env CFZombie 5
fb -[_NSZombie init]
fb -[_NSZombie retainCount]
fb -[_NSZombie retain]
fb -[_NSZombie release]
fb -[_NSZombie autorelease]
fb -[_NSZombie methodSignatureForSelector:]
fb -[_NSZombie respondsToSelector:]
fb -[_NSZombie forwardInvocation:]
fb -[_NSZombie class]
fb -[_NSZombie dealloc]
fb szone_error
If you run your App in a standard debugger now it halts on every memory error. You can see if it works if a long memory debugger help text is displayed if you start the debugging and watch the console.
精彩评论