Do Expression Breakpoints Work?

Not sure if I am getting the syntax wrong, but my conditional breakpoints seem to either always return false or always return true.

For example, mass > 0 always breaks when mass is 3, but mass == 3 never does.

1 Like

What's the type of mass?
If it is some floating point type e.g. Float or Double, it could be that the value is not exactly 3 but e.g. 3.00000001 which is not equal to 3. printing the value sometimes removes those inaccuracies, making debugging this issue a bit difficult.

You can read a bit more about this topic in this proposal about adding a function for approximate quality. It was returned for revision so you can't use the function proposed but explains the concept quite well.

2 Likes

Thanks for replying. mass is an Int

I tested it in a new Swift package and it is happening there too. I did swift package create --type executable and edited the file as in the animated GIF below (click to start it playing):

screen-recording

The extension settings are all default.

So am I doing something else wrong?

Trying this in Xcode it doesn't even work for mass > 0 but fails with:

error: stopped due to an error evaluating condition of breakpoint 1.1: "mass > 0"
Couldn't parse conditional expression:
error: <EXPR>:8:1: error: cannot find 'mass' in scope
mass > 0
^~~~

My guess is that mass is sometimes optimized away which lldb thinks too:

(lldb) v mass
(Int) mass = <no location, value may have been optimized out>

changing the example to

var mass = 3
print("a")
mass += 1
print(mass)

makes it at least work in Xcode for both expressions (mass > 0 and mass == 3).

I'm not sure if this is a bug and the compiler is not allowed to optimize variables away in debug builds or not.

2 Likes

Strange, I opened the same SPM project in Xcode and the same expression does work there, without reassignment.

It just works in Xcode 14 and doesn't work in VS Code. No idea why it didn't work for you.

But thanks for confirming that I was using the right syntax, and it's some configuration issue.

IMO variables should not get optimized away like that, so I think Xcode has got it right. Why is it optimizing the variables in VS Code even in a debug build?

I’m pretty sure that there’s a set of optimisations that are always performed even in debug mode, and one of them may be optimising away useless variables. The debug mode optimisations are only run on the SIL representation of your code iirc and not anything more low level, so they’re relatively basic. They’re also basic to ensure that debug builds are still performed quickly of course.

I haven't managed to get conditional breakpoints to work in VS Code. I guess it will be related to how CodeLLDB is trying to set these up and the expectations of the Swift version of LLDB. I can also quite frequently crash CodeLLDB by passing in bad conditions and the debugger will not start up again until I remove the offending breakpoint.

As an aside conditional breakpoints seem to work fine on Linux

I've added an Issue to investigate this further Investigate why conditional breakpoints don't work on macOS · Issue #432 · swift-server/vscode-swift · GitHub

2 Likes

I investigated this slightly further.

There are a number of ways that CodeLLDB evaluates expressions (simple, python, native). The default is simple and it checks if the value being evaluated is a numeric type, otherwise it will treat is as a string. It appears the issue is the Swift version of LLDB doesn't return Int as a numeric type. So the expression fails.

Luckily native expressions work. You can enable these either by prefixing your expression with /nat eg /nat mass == 3 or preferably you can default CodeLLDB to use native expressions all the time in the CodeLLDB Settings. Set lldb > Launch: Expressions to native and your conditional breakpoints should work.

See Conditional Breakpoints don't work with macOS version of Swift LLDB · Issue #927 · vadimcn/codelldb · GitHub for more details

5 Likes

Thank you so much! I'll try the native expressions.