Calling ConstructObject in a Function Returning NULL

Hi,

I’m trying to figure out why an object created with ConstructObject is set to NULL when leaving the function where it was created. I assume that this is somehow related to the GC, but I do not understand why and what I can do against it.

My CreateAndAddTeam-function will call CreateTeam, where I construct a new team.
In CreateTeam, the team is properly constructed, meaning, not NULL. But after returning to the calling function (in this case CreateAndAddTeam), the returned pointer is set to NULL.

Below is the code:

/**
* TRUE, if the team was added to the team manager.
* @param teamType	The team to create and add
* @param team		the created and added team or NULL
* @param bUnique	should only be one team of this type (default = true)
* @return true: team added by team manager, false: else
*/
bool UTeamManager::CreateAndAddTeam(TSubclassOf<class UBaseTeam> teamType, UBaseTeam* team, bool bUnique)
{
	bool		ok		= true;

	if (bUnique || bForceUniqueTeamTypesOnly)
		ok = !HasTeamType(teamType);

	// Creates and adds the team
	ok = ok && CreateTeam(teamType, team);
	ok = ok && (team != NULL);
	ok = ok && AddTeam(team);

	if (!ok)
		team = NULL;

	return ok;
}

/**
* Creates the team from a team type.
* @param teamType	The type of the team
* @param team		The team created (or null)
* @return			true: successful, false: else
*/
bool UTeamManager::CreateTeam(TSubclassOf<class UBaseTeam> teamType, UBaseTeam* team)
{
	bool okay = false;
		 team = NULL;


	team = ConstructObject<UBaseTeam>(
		teamType,
		this,
		NAME_None,
		RF_NoFlags,
		NULL,
		false,
		NULL);

	okay = (team != NULL);

	return okay;
}

When looking at the runtime variables, the following can be observed:

  • After calling ConstructObject in the function CreateTeam-function (just before returning to the calling function)

  • Directly after returning from CreateTeam in the CreateAndAddTeam-function

Thanks for your help.

~Julian

It’s not the GC, you’re changing what the team pointer in CreateTeam() points to but this is not the same pointer as the team in CreateAndAddTeam(), it’s just a copy. So the original team pointer in CreateAndAddTeam() remains unchanged (and thus null if it was null when you called CreateTeam()). If you want to change the original pointer you have to pass a pointer to it (a pointer to a pointer), like so:

bool UTeamManager::CreateAndAddTeam(TSubclassOf<class UBaseTeam> teamType, UBaseTeam** team, bool bUnique)
{
    // ... snip ...

    ok = ok && CreateTeam(teamType, team);
    ok = ok && (*team != nullptr);
    ok = ok && AddTeam(*team);

    if (!ok)
        *team = nullptr;

    return ok;
}

bool UTeamManager::CreateTeam(TSubclassOf<class UBaseTeam> teamType, UBaseTeam** team)
{
    //... snip ...

   *team = ConstructObject<UBaseTeam>(/* snip */);
   okay = (*team != nullptr);
   return okay;
}

Of course since neither of those methods actually make use of the original value of the team pointer it doesn’t really need to be a parameter and you could just return a pointer to the new team object (or nullptr in case of failure) instead of returning a boolean.

Ah, yes. My experience with C++ is a bit rusty, but you are totally correct, I need to do this pointer-pointer thing (or alternatively rewrite the function).
Sorry for this stupid question and thank you very much for your help!