I have a simple question about debugging on Xcode and GDB.
I often run into an error:
unrecognized selector sent to instance 0x1081ad0
which makes the program load into GDB. Is there an easy way to examine what instance is located in that memory from GDB?
po 0x1081ad0
po = Print Object.
You can even call methods, like
po [myArray objectAtIndex:0]
Note that it only works on objects, so
po 1
will crash your program.
Steven is correct — the gdb command po is a shortcut for print-object, which actually calls -debugDescription (not -description, as you might expect) on the object provided as an argument. In many cases you'll see the same result from both methods, since one calls the other unless overridden. (See the related Note: callout on this Apple technote for details. Note that in their code sample, po $r3 prints the contents of a PowerPC register, but you can use any object pointer/reference, including Intel registers, etc.)
Also, be aware that print-object will only work on valid objects that haven't been deallocated. It won't help at all if you're sending a message to a borked pointer. Given the error you cited, though, it would seem that it's a valid object instance, it just doesn't implement the method you're trying to invoke.
It's also remotely possible that the object has already been destroyed. This answer should help in that case.
Edit:
There are other ways to "examine" objects in the debugger. I asked this SO question about Xcode data formatters, which is one way you can determine how a custom class appears in the Summary column of the debugger. The documentation linked from that question explain how it works. I've found the summary approach to help a lot with seeing the state of an object.
There are a couple of things you can do.
You can insert a break point that will trigger every time you have an exception, so basically create a break point for this (go to breakpoints and create a new one): -[NSException raise]
Alternatively, you can actually see what the object at that mem location is:
info symbol 0x1081ad0 or
info line *0x1081ad0
There's more info at the cocoadev wiki entry for exceptionhandling and debugging tips for objective C at cocoawithlove.
Your instance is not valid. You have release the object somewhere else, but you did not clear out your pointer... enable Zombie detection.
Related
I made a breakpoint in Xcode with the jump commend to force passing some condition, but when it execute to line 168 it crash with message
"Thread 1: EXC_BAD_ACCESS (code=1, address=0x1)"
why did that happen?
the console logged:
warning: MoreMultitypeCollectionViewCell.swift:178 appears multiple times in this function, selecting the first location:
MoreMultitypeCollectionViewCell.(updateButtonStateCkeck in _9A12557DCAB30EEB52DC7C2EA09487CD)() -> () + 1580 at MoreMultitypeCollectionViewCell.swift:178
MoreMultitypeCollectionViewCell.(updateButtonStateCkeck in _9A12557DCAB30EEB52DC7C2EA09487CD)() -> () + 1600 at MoreMultitypeCollectionViewCell.swift:178
my questions are:
How should I type in lldb to select location?
Is there a better way to force passing into If Statement without change code and rebuild project?
sometimes when I type 'po' in lldb or click print description in variable view, it will show fail message, how is that?
1) In lldb, the equivalent command is thread jump and you can specify an address as well as a line number there.
2) thread jump or the Xcode equivalent is an inherently dangerous operation. If you jump over the initialization of some variable, you will be dealing with bad data now and will likely crash. That sort of thing you can sometimes spot by eye - though Swift is lazy about initialization so the actual initialization of a variable may not happen where you think it does in the source. There are more subtle problems as well. For instance, if you jump over some code that as a byproduct of its operation retains or releases an object, the object will end up under or over retained. The former will cause crashes, the latter memory leaks. These retains & releases are generated by the compiler, so you can't see them in your source code, though you could if you look at the disassembly of the code you are jumping over.
Without looking at the code in question, I can't tell why this particular jump caused a crash.
But you can't 100% safely skip some of the code the compiler choose to emit. Looking at the disassembly you might be able to spot either (a) a better place to stop before the jump - i.e. stop past some retain or release that is causing a problem or jump to an address in the middle of a line so you still call a retain that's needed. You'll have to figure this out by hand.
3) There's not enough info to answer this question.
BTW, your image links don't seem to resolve.
When debugging a C# application using WinDbg, I know how to list the objects of a certain type with !dumpheap. For example:
!dumpheap -stat -type CefSharp.Wpf.ChromiumWebBrowser
Statistics:
MT Count TotalSize Class Name
00007ffa08364978 1 32 CefSharp.Wpf.ChromiumWebBrowser+<>c__DisplayClass1f
00007ffa08336f48 1 32 CefSharp.Wpf.ChromiumWebBrowser+<>c__DisplayClass22
00007ffa0833fa18 2 64 CefSharp.Wpf.ChromiumWebBrowser+<>c__DisplayClass25
00007ffa08364748 4 128 CefSharp.Wpf.ChromiumWebBrowser+<>c__DisplayClass28
00007ffa083123c0 1 824 CefSharp.Wpf.ChromiumWebBrowser
00007ffa08361fe0 115 3680 CefSharp.Wpf.ChromiumWebBrowser+<>c__DisplayClass10
Now, I am wondering if I can execute a method of one of these objects using WinDbg. For example, I know this object has a ShowDevTools() method, how can I execute it?
TLDR: I've never seen it working until now. A related question is unanswered since 2011. If it would be easily possible, some smart people like Steve Johnson (author of SOSEX) would probably have implemented this in an extension. There's also no such command in netext. The closest there is !weval but it works on members only.
While you have a list of objects now, you'll first need to find the methods that are available at those objects:
!dumpmt -md <MT column from !dumpheap>
To call a method, there's the .call command, but it explicitly states that .NET is not supported:
Managed code cannot be called by this command.
However, .NET is not only managed. After the JIT compiler has processed the IL code, you have native code like in C++.
The !dumpmt -md command already told you whether or not the managed method has already been JITted. There are 3 possibilities:
None: the method has not been jitted
PreJIT: the method has been jitted by NGen
JIT: the method has been jitted
From !dumpmt -md you have a method descriptor, you can use
!dumpmd <method descriptor>
From there, you get a native code address, which could possibly be used for a .call. Unfortunately, the next problem occurs:
0:006> .call 011f0500
^ Couldn't resolve '.call 011f0500'
This error message means that WinDbg was unable to resolve the symbols for that method. While you have PDBs for your DLL, the JIT compiler does not produce a PDB for the JITted code.
Therefore you need to specify a prototype as defined in the documentation:
.call /s Prototype Function( Arguments )
Allows you to call the function that is specified by Function even though you do not have the correct symbols. In this case, you must have symbols for another function that has the same calling prototype as the function you are trying to call.
At this point, we have the following open questions:
where do I get a good prototype from?
what do I do if the method was not JITted?
I'm sorry that this "answer" does not resolve your issue. It may only give some insight on how difficult the situation is.
I have a wxWidgets/GTK based application that works well - except for one installation on an Debian Squeeze ARM system. There it crashes when the user just activates the main window of it. To find the reason for that I added a signal handler to the application and use libunwind out of that signal handler to find the source for the crash. During a test that worked fine, when the software writes e.g. to address 0x0 libunwind correctly points me to the function where that happens.
But the results for the system where the crash appears unexpectedly are a bit strange, they seem to happen outside of my application. One crash comes from a function with no name (here libunwind returns an empty string), and one is caused by "malloc_usable_size", a system function which should never die this way.
So...what to do next? All ideas, suggestions or any other hints are welcome since I'm not sure how to contunue with that problem...
Check for buffer overrun or overwriting some memory unexpectedly for any structures, pointers, memory locations for items returned by library functions.
Check for invalid pointer frees in your code for the library allocated pointers that you are using.
May be using valgrind would also help.
This should be so simple, and yet, it is evading me: When stopped at a breakpoint in the Xcode/gdb debugger, I wish to find the current refcount of an object derived from NSObject. How can I do this? I can't seem to find a way, and it is driving me mad.
Even better: go to the console (command+shift+r) and type:
p (int)[objectName retainCount]
And press enter. You can execute any statement you want on that console (it's GDB, at least for now), making whatever code calls you want, and it'll still try — and usually succeed — to come up with a result. 'p' is to print the result as a C primitive, 'po' would print the result as an Objective-C class (ie, by calling 'description' just as if you'd NSLog'd the instance). The 'int' is there because GDB can't always determine the return types at runtime, in which case you need to tell it.
It's as simple as
NSLog(#"retainCount:%d", [objectName retainCount]);
where objectName is whatever you named the object in question.
Please note that this does not work on NSStrings since they are managed differently.
For more info:
http://www.karlkraft.com/index.php/2009/04/22/dont-use-non-mutable-objects-to-understand-leak-detection/
I have a pretty weird problem in my iPhone app which is, I think, related to memory getting corrupted:
At one point, I need to sort an array, which I do with -[sortArrayUsingFunction].
The result is not correct unless I either allocate some memory with something like void *test = malloc(2 * sizeof( int )) before the method call or have, e.g., a call to NSLog() (which is never invoked) in the sorting function.
In other words: the sorting only works if I slightly increase the memory that was used before calling the sorting function. I think this is because at some point, memory gets corrupted.
How do you debug something like this?
It sounds like some of your code is using already released objects. A lot of help with debugging this kind of errors is provided in Apple’s great Mac OS X Debugging Magic tech note, especially the foundation part.
For your case I'd disable autorelease pools (setting the environment variable NSEnableAutoreleasePool=NO) or use the zombie feature (NSZombieEnabled=YES) to find places where you send messages to released objects.
Try running your program in the simulator under Valgrind:
http://valgrind.org/
And how to use it under the simulator:
http://landonf.bikemonkey.org/code/iphone/iPhone_Simulator_Valgrind.20081224.html
You may have to change the VALGRIND path in the code example depending on where it gets installed.
Such things can be a challenge to debug. There are some tools for detecting out-of-bounds accesses and such on other platforms, so I presume there would be something for the iPhone, however I don't know of any.
Perhaps you should store two copies of the array, and compare them for differences. Print out the differences. The nature of the "junk" that was introduced to one of the arrays might give a hint as to where it came from.
Also just go through the code that runs before this point, and re-read it (or better yet, get someone else to read it). You might spot a bug.