How to debug C++

I’ve searched high and low, and I’m still having problems with debugging c++ code. The problem is that when stepping through the code, it appears to be optimized: the execution order in the debugger is not straightforward. Variables are not initialized or updated at the point when the execution point steps past that line in the source. What is the recommended workflow for working with C++ code and the editor? I have been running the editor, then launching VS and attaching the debugger to the running editor instance. The configuration in VS is set to “DebugGame Editor” (is this the correct one?). I’ve come across posts recommending using the “Debug Editor” configuration, but that doesn’t exist. Any help with settings to make it possible to debug unoptimized code would be greatly appreciated!

If you want to debug the engine then you need to use the Github version of the engine. You build it from source and you will see “Debug Editor” is available.

I am not trying to debug the engine – just my game classes.

Then DebugGame_XXX is sufficient. If you’re stepping over optimized code then that must be engine code.

I am stepping through code in a class I added (derived from UCharacterMovementComponent).

Maybe show a few lines around an example in your code and it will make more sense to me.

This is the beginning of the method I’m debugging. As an example, the execution pointer never even goes to the if (!RPOwner) line (presumably because the compiler can determine at compile time that it is not possible for the cast to fail, though to be honest I’m not 100% sure how it can be certain of that). It also skips past remainingTime -= timeTick, but jumps back to it later. Same with the initialization of the const local variables.

It seems like the editor is still compiling it as a development version. Is there something else I need to do besides set the configuration to “Debug Game Editor” in VS?

void URPCharacterMovementComponent::PhysSwinging(float deltaTime, int32 Iterations)
{
	//REMOVE: for debug purposes
	//deltaTime *= 0.3f;

	ARobotPlatformerCharacter* RPOwner = Cast<ARobotPlatformerCharacter>(CharacterOwner);
	if (!RPOwner)
	{
		UE_LOG(LogRobotPlatformer, Error, TEXT("Trying to use PhysSwinging with a non-RobotPlatformerCharacter!"));
		return;
	}

	if (deltaTime < MIN_TICK_TIME)
	{
		return;
	}

	float remainingTime = deltaTime;
	while ((remainingTime >= MIN_TICK_TIME) && (Iterations < MaxSimulationIterations))
	{
		Iterations++;
		const float timeTick = GetSimulationTimeStep(remainingTime, Iterations);
		remainingTime -= timeTick;

		const FVector OldLocation = UpdatedComponent->GetComponentLocation();
		const FQuat PawnRotation = UpdatedComponent->GetComponentQuat();
		const FVector OldVelocity = Velocity;
		//UE_LOG(LogRobotPlatformer, Warning, TEXT("Starting\tLocation: %s Velocity: %s"), *OldLocation.ToString(), *OldVelocity.ToString());

It’s definitely not certain that the cast will fail. Cast is determined at runtime.

And yes. As far as my experience goes, I’ve never seen it skipping code in DebugGame builds. The jumping around thing sounds familiar. I always figured it was because there was more than one thread running that code. And it never seemed to stop me from debugging what I needed.

Can you set a breakpoint (and it stays there when the debugger is up) at the “return” statement in the if(!RPOwner) block? Note that they go away for a bit while the debugger loads symbols but they should come back.

Changing build target to DebugGame Editor is a good start, but it doesn’t work for all cases. When it happens, you can manually disable optimization for specific portion of code. Then you can freely step through it.

But keep in mind that even then, it might not work perfectly (or it might not seem like it does). I don’t know this for sure, but when you step through code it sometimes falsifies the line at which execution of the program actually is. I’m guessing that it’s caused by usage of macros above the line you’re at but I’m not sure about that.

It won’t work as expected when code from the game and from VS doesn’t match.

Anyway, to disable optimization for given code just use this:

#pragma optimize( "", off )

// your code

#pragma optimize( "", on )

It’s meant to be used temporary for the time you want to test given code. It rather shouldn’t be left out there in release code afaik.

I never had to use this in functions implemented in headers so I’m not sure if it would work there.
For inline, header functions you could use FORCEINLINE_DEBUGGABLE macro. I’ve seen it couple times in engine, but I never had to test that.

Usage:

FORCEINLINE_DEBUGGABLE void Function()
{
	// Do stuff
}

See engine example (github account linked to UE account is required to read this)