Why do FGuids within c++ structs cause the error “FSomeStruct::SomeFGuid is not initialized properly.” in the following struct format?
USTRUCT(BlueprintType)
struct FS_Test : public FTableRowBase {
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite, EditAnywhere)
FGuid ID;
// Initialize
FS_Test() {
ID = FGuid::NewGuid();
}
FS_Test(FGuid InID) {
ID = InID;
if (!ID.IsValid()) {
ID = FGuid::NewGuid();
}
}
// Operators
bool operator==(const FS_Test& Other) const {
return (
ID == Other.ID
);
}
}
*Edit so this is annoying, at first I thought the error appeared because the FGuid is set in the constructor, or maybe even because I use if / else, but after replacing the thing with an initialiser list the error remains. Am I missing something obvious?
USTRUCT(BlueprintType)
struct FS_SomeStruct : public FTableRowBase {
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite, EditAnywhere)
FGuid ID;
// Initialize
FS_SomeStruct()
: ID (FGuid())
{
}
FS_SomeStruct(FGuid InID)
: ID (InID)
{
if (!ID.IsValid()) {
ID = FGuid::NewGuid();
}
}
// Operators
bool operator==(const FS_SomeStruct& Other) const {
return (
ID == Other.ID
);
}
};
Bump . If this is the correct way to do it, that would also be an answer. I think UE might just be acting weird on USTRUCT ? I have 3 structs where this happens and one where it doesn’t, using nearly the same implementation. The only difference being that the working UPROPERTY is marked (BlueprintReadOnly, VisibleAnywhere) while the non working ones are marked (BlueprintReadWrite, EditAnywhere). That would be strange wouldn’t it…
My guess here is that the FGuid default constructor does nothing, in which case it’ll be uninitialized memory. You may need to use an explicit initializer constructor for your default constructor.
Okay this actually explains it. The problem is that FGuid actually has two declarations - one in the header you mentioned, the other in NoExportTypes.h
The warning about uninitialized struct members comes from the Unreal Header Tool, and UHT parses the duplicate FGuid from NoExportTypes.h which has no initialization or constructors.
So really it’s an oversight from Epic. You can ignore the warning, since in actual C++ code the native FGuid will be used. The stub in NoExportTypes just generates the required reflection data to expose that type to Blueprint. There isn’t a workaround for this AFAIK.
Is it possible that certain UPROPERTY specifiers alter this behavior? It’s odd that this problem occurs in a few (but not all) structs with FGuid where the only difference are the specifiers and meta. I also see other data types in the NoExportTypes.h like FTransform but none of these generate the message. Why is that?
*Edit, forgot to note that the error is not a visual studio one but a log entry in UE.
/// [PropertyMetadata] Used for bypassing property initialization tests when the property cannot be safely tested in a deterministic fashion. Example: random numbers, guids, etc.
IgnoreForMemberInitializationTest,
If you are interested in how the check is done, take a look at FindUninitializedScriptStructMembers in Runtime\CoreUObject\Private\UObject\Class.cpp.
Basically it’s looking for uninitialized struct members to warn you about (undefined behavior is not fun).
At a glance, it seems like struct properties are checked by seeing if the given property will have the same value for 2 different variables. This just won’t work with things that are non-deterministic by design; random numbers, uids (if you make 2 uids, you want them to be different, otherwise it wouldn’t be very useful for identifying things), and the like… the test will just fail in case the property is initialized properly. For these cases you can use the meta tag to skip the check.
“Not initialized properly” warning now showing on any type even booleans if a struct / datatable bugs somehow. All affected properties are within datatables.
No I didn’t. It appears that it doesn’t pop up for all but very specific properties and when it does it keeps going on. Something must be broken in the engine.
No solution, but for anyone reading I tried creating a new clean project and migrating the affected structs, datatables and their dependencies to a new module with no success. Looking at the view count on this post it’s quite a common issue.
The error “is not initialized properly” essentially means “give me an initial value”. This applies only to structs, I believe. You can assign it on the declaration line or in a constructor function.
For example,
FGuid ID = FGuid(0,0,0,0);
Although you do assign it NewGuid() in the constructor. Maybe it’s seeing that as still uninitialized. A lot of times the default constructor in the docs will indicate that it is uninitialized.