LLDB convenience variable object assignment is nil? - xcode

Ran into this phenomenon while debugging something else and am curious:
(lldb) po (NSException *)($eax)
$3 = 0x0d16c510 Test exception message
(lldb) expr NSException *$exception = (NSException *)($eax)
(lldb) po $exception
$exception = 0x00000000 <nil>
I'm running an iOS app in the 6.1 Simulator. Why would assigning a convenience variable give me nil when referencing $eax directly gives me an object?

I tried to reproduce this with Xcode 4.6.2 but could not. I created a template iOS app and launched it in the simulator. I didn't bother getting to a place where I had an exception in a register - I but the register value is the important thing here.
(lldb) reg read eax
eax = 0x10004005
(lldb) p (NSException*) ($eax)
(NSException *) $0 = 0x10004005 <not an Objective-C object>
(lldb) expr NSException*$exception = (NSException *)($eax)
(lldb) p $exception
(NSException *) $exception = 0x10004005 <not an Objective-C object>
(lldb)
In your example $exception had a value of 0x0 but when I tried this with 4.6.2, it looks like it is working. What version of Xcode were you using?

Related

NSNumber's stringValue print other strings what we don't want

(lldb) po [#(70.033) stringValue]
70.033
(lldb) po [#(80.138) stringValue]
80.13800000000001
(lldb) po [#(70.138) stringValue]
70.13800000000001
(lldb) po [#(100.01) stringValue]
100.01
(lldb) po [#(90.03) stringValue]
90.03
(lldb) po [#(90.01) stringValue]
90.01000000000001
(lldb) po [#(900.01) stringValue]
900.01
(lldb) po [#(100.01) stringValue]
100.01
(lldb) po [#(80.01) stringValue]
80.01000000000001
Is this a bug form the NSNumber? Or a mistake with my Mac?
No, it is not a bug. It is just the standard issue with the internal representation of numbers.
So (in Swift):
var a = 0.15 + 0.15
var b = 0.1 + 0.2
print (a == b) // can be false!
print (a >= b) // can also be false!
var c = 80.138
print(c) // 80.138
print (c - 80.0 - 0.138) // 5.218048215738236e-15
There are many people observing this "strang" behaviour, in almost any programming language. Just check some web sites like stackoverflow.com:
strange output in comparison of float with float literal
or, with nice images:
https://bitbashing.io/comparing-floats.html

How to get c++ enum value in Xcode?

I would like to know if this is possible to get the value of c++ enum item in Xcode.
In Visual Studio you just have to hover the item and you got a tooltip with its value but it does not do the same in Xcode.
I also tried to print the value in lldb console without success.
For instance with this simple enum:
enum Params{
eP1,
eP2,
eP3,
eP4,
eP5,
};
I tried different ways like p eP1 or p Param::eP1.
I also tried with an enum class with the same result.
At present, you have to use enumName:enumElement, but that is working for me:
> cat foo.cpp
#include <stdio.h>
enum Params
{
eP1,
eP2,
eP3,
eP4
};
int main()
{
enum Params elem = eP1;
printf ("%d\n", elem);
return 0;
}
> lldb a.out
(lldb) target create "a.out"
Current executable set to 'a.out' (x86_64).
(lldb) b s -p printf
Breakpoint 1: where = a.out`main + 29 at foo.cpp:14, address = 0x0000000100000f6d
(lldb) run
Process 26752 launched: '/private/tmp/a.out' (x86_64)
Process 26752 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000f6d a.out`main at foo.cpp:14
11 int main()
12 {
13 enum Params elem = eP1;
-> 14 printf ("%d\n", elem);
^
15 return 0;
16 }
Target 0: (a.out) stopped.
(lldb) expr Params::eP1
(int) $0 = 0
If you still can't get this to work, can you post a more complete example where it fails?
The problem for lldb, BTW, is that the debug information is organized into the full debug information and then a name->info accelerator table. lldb depends on the accelerator tables for lookup (otherwise it would have to go looking through all the debug info which can get pretty slow for big apps). The accelerator tables at present only have the name of the enum, not the element names.

How can I find out what is changing an object (or a simple variable) in Xcode 4 / lldb?

In some debuggers this is called "setting a trap" on a variable. What I want to do is trigger a breakpoint on any statement that changes the object. Or changes a property of the object.
I have an NSMutableDictionary that gets a value/key added to it but I can't find any statement that could be doing that.
You can set a watchpoint (from here):
Set a watchpoint on a variable when it is written to.
(lldb) watchpoint set variable -w write global_var
(lldb) watch set var -w write global_var
(gdb) watch global_var
Set a watchpoint on a memory location when it is written into. The size of the region to watch for defaults to the pointer size if no '-x byte_size' is specified. This command takes raw input, evaluated as an expression returning an unsigned integer pointing to the start of the region, after the '--' option terminator.
(lldb) watchpoint set expression -w write -- my_ptr
(lldb) watch set exp -w write -- my_ptr
(gdb) watch -location g_char_ptr
Set a condition on a watchpoint.
(lldb) watch set var -w write global
(lldb) watchpoint modify -c '(global==5)'
(lldb) c
...
(lldb) bt
* thread #1: tid = 0x1c03, 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16, stop reason = watchpoint 1
frame #0: 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16
frame #1: 0x0000000100000eac a.out`main + 108 at main.cpp:25
frame #2: 0x00007fff8ac9c7e1 libdyld.dylib`start + 1
(lldb) frame var global
(int32_t) global = 5
List all watchpoints.
(lldb) watchpoint list
(lldb) watch l
(gdb) info break
Delete a watchpoint.
(lldb) watchpoint delete 1
(lldb) watch del 1
(gdb) delete 1
Watchpoints are used to track a write to an address in memory (the default behavior). If you know where an object is in memory (you have a pointer to it), and you know the offset into the object that you care about, that's what watchpoints are for. For instance, in a simple C example, if you have:
struct info
{
int a;
int b;
int c;
};
int main()
{
struct info variable = {5, 10, 20};
variable.a += 5; // put a breakpoint on this line, run to the breakpoint
variable.b += 5;
variable.c += 5;
return variable.a + variable.b + variable.c;
}
Once you're at a breakpoint on variable.a, do:
(lldb) wa se va variable.c
(lldb) continue
And the program will pause when variable.c has been modified. (I didn't bother to type out the full "watch set variable" command).
With a complex object like an NSMutableDictionary, for instance, I don't think watchpoints will do what you need. You would need to know the implementation details of the NSMutableDictionary object layout to know which word (or words) of memory to set a watchpoint.

Memory corruption after using NSOpenPanel

I got a problem that leads to my program reporting malloc corruption when I use NSOpenPanel. My code is mainly C (not using Xcode) and what I do is something like this:
main(..)
{
[NSApplication sharedApplication];
... create window etc, no problem
[NSApp run];
}
Later I call something like this
openFileDialog(..)
{
// tried to create NSAutoreleasePool and things here bit still breaks
NSOpenPanel* open = [NSOpenPanel openPanel];
int res = [open runModal]
...
}
After exiting the function (or a bit later) I will get
test (1948,0x7fff7d852960) malloc: * error for object 0x7ff19b879608:
incorrect checksum for freed object - object was probably modified after being freed.
* set a breakpoint in malloc_error_break to debug
Ideas?

GDB If statement return values?

Is there a way I can read if statements being evaluated? I mean, like get the return value of realpath in -
if(realpath(path.c_str(), realPath) == 0)
You can step into and finish realpath function. The returned value will be printed on screen.
at the gdb prompt (if you got debug symbols enabled when you compiled)
print realpath(path.c_str(),realPath)
it will print the result, very nifty.
If you had a memory pointer laying around on your code, you could use GDB to allocate new memory space for it it, and use it to store the result of the expression you want to evaluate.
Check this page for more info.
(gdb) set variable p = malloc(sizeof(int))
(gdb) print p
$2 = (int *) 0x40013f98 (address allocated by malloc)
(gdb) set variable *p = 255
(gdb) print *p
$3 = 255

Resources