Debugging Unreal projects / Why can't I watch variables on the stack in Visual Studio?

In unreal, be it code from an actual project or code from the engine, I can rarely see a local variable’s value in Visual Studio. Other times I see the value but it’s totally inaccurate. This goes for function parameters and the rest. I also tried to recompile without inlining and it doesn’t change anything. This is really annoying as it takes quite an effort to not make this possible since it’s available in Visual Studio by default. By some magical reasoning I can watch variables just fine in Xcode but can’t attach Xcode to an iOS Unreal app. I can attach the debugger to any other app just fine, but with unreal it just hangs. I also can’t deploy iOS builds directly from Xcode because they crash in some init code saying they can’t find a localization file and I think this is because if I deploy from Xcode the project is not set up to deploy assets ! I can only deploy to iOS from the OSX editor build. Why is it so hard to debug anything made with Unreal ?

It works fine for me, you have to be running in “DebugGame Editor” and actually debugging through VS of course, then I just copy-paste the name and paste it into the Watch thread.

Normally it helps to have inserted a breakpoint as well, you have to breakpoint the code to be able to see the variables at a given time.

So I have to use “DebugGame Editor” instead of the recommended “Development Editor” ? I was under the assumption that the development build had debug information anyway !

EDIT : It seems I already tried that from a previous “tip”. Let’s give a practical example though. I’m on DebugGame Editor config looking at :

void FDebugCanvasDrawer::DrawRenderThread(FRHICommandListImmediate& RHICmdList, const void* InWindowBackBuffer)

I’ve put RHICmdList in the watch and it says RHICmdList.NumCommands is 3452816845. Now I doubt that’s the real value by far.

Yeah, it’s all about your build configuration. When you use the wrong one, the compiler will optimize your binary executable a bit.

Behaviors of an optimized binary:
-If you try to follow the program counter, it will jump around instead of moving through the code sequentially. It “appears” to use JIT.
-You can assign a variable and a value to it, but that assignment won’t appear to happen until that variable is actually used in another part of code. If its not used, it gets optimized away.

Anyways, use the correct build configurations and you should be good :slight_smile:

Hello!

This can be confusing at first for sure, but like some other people have suggested, the most complete fix is to simply use a debug build configuration to not let the compiler optimize your code. The biggest problem with this however is that the debug builds are HORRIBLY slow. I have a pretty beefy setup, and I still get abysmal frame rates in the editor. You also need to rebuild fully unless you have a previous build already done, so switching to a full debug configuration is not always the best choice.

One alternative that I have started to use more often, unless I need to debug all over the engine source of course, is to use the optimize pragma instead.
Basically, just slap this around the function you need to step through and do a fast rebuild and the compiler will not optimize away your debug data:

#pragma optimize(“”, off)

YOUR FUNCTION HERE

#pragma optimize(“”, on)

Hope this helps!

Best regards,

5 Likes

Unfortunately, you’ll always need to make some kind of tradeoff between speed from compiler optimizations and ease of debugging. As a general rule I almost always run using DebugGame or a very similar configuration. This will optimize most of the engine code but leave game specific code unoptimized for easier debugging. This works well most of the time. There are a few things you can do if you need to debug engine code.

If there’s a particular function or file that I need to debug I’ll usually add “PRAGMA_DISABLE_OPTIMIZATION” near the top of the file. This macro works is very similar to the #pragma mentioned but is safer for cross platform development. If you need to debug a whole module you can turn off optimizations in its build.cs file by setting OptimizeCode to CodeOptimization.Never. For example, if I needed to do some debugging in the Persona module I’d change the beginning to look something like this:


public class Persona : ModuleRules
{
	public Persona(TargetInfo Target)
	{
		OptimizeCode = CodeOptimization.Never;

Just make sure to take that line out again when you’re done so you don’t keep paying a performance penalty for code you’re not debugging. If what you need to work on isn’t restricted to a single module you may need to run in the Debug configuration. This will be very slow on most machines so I’d avoid doing it if possible.

Ciprian At Facerig,
Have you tried posting your iOS problems on AnswerHub? It’s usually a better place to bring up bugs since they can be automatically added to our bug tracker. Here’s a post with instructions for how to do it: How do I report a bug? - Programming & Scripting - Epic Developer Community Forums. If you don’t have all the info for a bug just try to give as much as you can.

4 Likes

I’ve now switched to “Debug Editor” and after 40 minutes of building I can now see all the variables on stack. What bothers me though is that ok maybe the engine should be compiled with optimizations on, but not even my C++ project was debuggable. And on the first config I tried the “Development Editor” I manually disabled all inlining & stuff and I still couldn’t see the variables on the stack (and it did trigger a full rebuild when I changed these ). It looks to me like the UBT is a real pain to work with. This and the fact that I can’t exclude .cpp-s from being compiled (more info here How to exclude files from being compiled ? - C++ - Epic Developer Community Forums ). Is there any way to build Unreal without UBT though ?

You don’t need to build the entire engine, only your project. If you’re using source code it’s probably more complicated.

As for UBT, no there’s no way to compile without it.

I’m not fighting against it. I’m arguing that UBT is a downgrade if you come from a Visual Studio or Xcode background.

1 Like

@Epic, can we please have some more configuration to control the builds using the inescapable UBT?