Project Corruption on Mac

I have had frequent problems with various projects being corrupted on Mac OSX 10.9 and 10.10 using UE4 Editor 4.6.x and now 4.7.5. It has happened on the ShooterGame example, on simple test projects and now on a project based on the FPS Wiki Tutorial. I am using XCode 6.2 on a Mac Pro with 22GB of RAM, a 5770 video card and Mid 2010 2x2.4 Ghz Quad Core Xeon.

I believe I’ve isolated this to class changes in C++. I can recreate it in my current test project by adding code, compiling, running one or many successful tests, then closing the project, and attempting to reopen it. I can easily believe that I am creating code that is incorrect in some manner (especially in this case because I am experimenting with creating dynamic TArrays of structs), but the fact that the editor allows the project to work, then save, yet will not permit it to be opened again, seems like it could be a bug. With my current tests, it seems too consistent to be a memory error on my computer. The test environment is trivial and has only rudimentary objects and textures (see Wiki FPS Tutorial)

The issue shows up on reopening the project by the editor aborting with a dump. The dump always lists whatever class I was working on as the culprit in creating a memory error. I can correct the corruption by loading XCode and double clicking on the .xcodeproj in the UnrealProjects/Projectname directory, loading it, removing some code, running a Clean, then a Build and exiting XCode. Then I remove the .dylib files in the Binaries/Mac directory, restart the project and it will load after it recreates the .dylib file.

While my code may cause problems, I have recreated this with adding a simple display into a class, testing it, saving it, then attempting to reload the project. My question is, is this a bug of UE4 or is it normal to need to have perfect code in the previous session to avoid being unable to load the project on next invocation of the editor?

I have sent several crash reports on this over the last month.

EDIT2:

As requested, here is an example of code that does this. I removed the UE4 macro struct version I was experimenting with because it vastly complicated the issue. Here is the simpler, hopefully good code that still reproduces the problem. I have made simpler code that also did the same thing.

In the project/Engine h file, I place this struct definition:

struct FInventoryDefinition {
    int32 IType;
    FString IName;
};

Then in the GameMode.cpp, I place the following:

at the top:

FInventoryDefinition Inventory[5];

at the bottom:

bool AFPSGameMode::LoadInventory() {
    Inventory[0].IType=0;
    Inventory[0].IName="Machine Gun";
    Inventory[1].IType=0;
    Inventory[1].IName="Bazooka";
    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("Inventory Loaded"));
    return(true);
}

In the constructor, I place this:

if(LoadInventory()) {
   GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("Inventory Reported Okay"));
}

I compile using the Compile button in the editor. It completes with a clean compile log and I Play one or more times. The code seems to work each time. I then close Unreal Editor and wait a few minutes. Open the .uproject file and get a crash with a dump that begins like this:

MachineId:deleted
EpicAccountId:deleted

Generating report for minidump

Application version 4.7.5-2503383+++depot+UE4-Releases+4.7
 ... built from changelist 2503383
 ... based on label ++depot+UE4-Releases+4.7

OS version 10.10.2.5396
Running 8 x64 processors
Exception was "SIGSEGV: invalid attempt to access memory at address 0x78d"

Source context from ""

<SOURCE START>
<SOURCE END>

<CALLSTACK START>
AFPSGameMode::AFPSGameMode(FObjectInitializer const&) Address = 0x13d460bfa [/Users/myusername/Documents/Unreal Projects/FPSProject 4.7/Source/FPSProject/FPSGameMode.cpp, line 17] [in UE4Editor-FPSProject-8591.dylib]
UClass::CreateDefaultObject()  Address = 0x105820341 (filename not found) [in UE4Editor-CoreUObject.dylib]
ProcessNewlyLoadedUObjects()  Address = 0x1059a98aa (filename not found) [in UE4Editor-CoreUObject.dylib]
TBaseStaticDelegateInstance<void ()>::ExecuteIfSafe() const  Address = 0x1058517c7 (filename not found) [in UE4Editor-CoreUObject.dylib]
TBaseMulticastDelegate<void>::Broadcast() const  Address = 0x1050a6ad8 (filename not found) [in UE4Editor-Core.dylib]
FModuleManager::LoadModuleWithFailureReason(FName, EModuleLoadResult&, bool)  Address = 0x10526a720 (filename not found) [in UE4Editor-Core.dylib]
FModuleDescriptor::LoadModulesForPhase(ELoadingPhase::Type, TArray<FModuleDescriptor, FDefaultAllocator> const&, TMap<FName, EModuleLoadResult, FDefaultSetAllocator, TDefaultMapKeyFuncs<FName, EModuleLoadResult, false> >&)  Address = 0x10a3c1bda (filename not found) [in UE4Editor-Projects.dylib]
FProjectManager::LoadModulesForProject(ELoadingPhase::Type)  Address = 0x10a3d21ce (filename not found) [in UE4Editor-Projects.dylib]
FEngineLoop::LoadStartupModules()  Address = 0x104ffd588 (filename not found) [in UE4Editor]
FEngineLoop::PreInit(wchar_t const*)  Address = 0x104fe8771 (filename not found) [in UE4Editor]
GuardedMain(wchar_t const*)  Address = 0x104ff2b64 (filename not found) [in UE4Editor]
-[UE4AppDelegate()  Address = 0x1050017c3 (filename not found) [in UE4Editor]
-[FCocoaGameThread()  Address = 0x105150278 (filename not found) [in UE4Editor-Core.dylib]
__NSThread__main__()  Address = 0x7fff97ba290a (filename not found) [in Foundation]
_pthread_body()  Address = 0x7fff946e7268 (filename not found) [in libsystem_pthread.dylib]
_pthread_body()  Address = 0x7fff946e71e5 (filename not found) [in libsystem_pthread.dylib]
thread_start()  Address = 0x7fff946e541d (filename not found) [in libsystem_pthread.dylib]
<CALLSTACK END>

Hi eagletree,

Can you post the code you added to your new class, and the type of class you made, so we can recreate it here? Additionally, it would be helpful to see the Crash Reporter dialogue that pops up after the crash, and the crash log from the project. Thanks!

Ben, I provided this above with the exception of the log (which I don’t know where to find). I hope I stated clearly enough that the code is likely very wrong (since repeated executions continue to add to the TArray between "Play"s, something really wrong there to have data persist over executions), but the issue is not being able to get back into the project once it’s closed. I’ve had this with nearly every project I’ve worked on where I alter any C++ code. My son, using a nearly identical system, only works on blueprints, does no XCode work and has not had this issue. I also forgot to mention that everything we do is OS X only, no IOS.

Hey eagletree-

When adding the USTRUCT() code you provided above to a custom Engine class there are compile errors relating to the ItemType and IType variables. Additionally, in the GameMode.cpp there are compile errors caused by FInventoryDefinition. Are there other includes that need to be added or other classes necessary for references?

Interesting. I received no compile errors. I removed all the USTRUCTS, GENERATED_STRUCT_BODY, and UFUNCTION calls as they were something I put in to try and get around the problem, not part of the original issue. After doing so, the issue persisted until removing the call to LoadInventory(). Again, I had no compile errors and at this point, the editor will open (after rebuilding in XCode and deleting the files/directories as mentioned originally).

This makes it sound like I should be getting compile errors but for some reason, am not. Oddly, I can load the project now, add the inventory load call back in and it “works”, until I close the editor and try to start again. Why would I not get compiler errors you are getting? I don’t get them whether using the Compile button in the editor or doing an external build with XCode.

On second reading of your reply, I realized I didn’t answer your question, but yes, it needed a #include of engine.generated.h if using the USTRUCT etc. I apologize for not including that. The better solution is as my last reply, remove all UE4 macros as they have no purpose here.

I dramatically simplified the code to recreate my problem. I hope it’s not inappropriate to revise the question that much, but it would have made it much longer. At this point I question if you can recreate this problem since it should be glaring if it was happening to everyone on an OSX UE4 implementation.

I wanted to update this. I found that since going to 4.7.5, I can’t make any change to the AGameMode, ACharacter, or AActor classes without causing this project corruption. On 4.6, it only happened sometimes. I would think you would need to look at what the editor generated for an xcodeproj to see how this could have occurred?

I believe I have discovered the source of the problem. If I include a display in any constructor for any of the classes, that does a display, or a call to a function that does a display, e.g.,

GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("some screen display"));

it will work until I close the project. Then, on reopening the project, it will be corrupted. Does this seem like a timing issue?

Hey eagletree-

I just wanted to confirm the repro steps to make sure I’m following the same setup that you’re using:

First you create a new class based on Engine and add:

struct FInventoryDefinition {
     int32 IType;
     FString IName;
 };

Then you add a new class based on GameMode. When you say that you add FInventoryDefinition Inventory[5]; at the top, what exactly do you mean?

Then

bool AFPSGameMode::LoadInventory() {
     Inventory[0].IType=0;
     Inventory[0].IName="Machine Gun";
     Inventory[1].IType=0;
     Inventory[1].IName="Bazooka";
     GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("Inventory Loaded"));
     return(true);
 }

is added at the bottom of the source file, correct? Is there anything other than the LoadInventory() function that has to be setup in the header file for the GameMode? Let me know if I’ve forgotten a step or left something out.

What I found (see last comment above, made 2 days ago), is that the problem can be created merely by adding the GEngine->AddOnScreenDebugMessage to the constructor of the AGameMode class or to any function that it calls. It takes only a single line for me to reproduce it (as shown in the other comment). It was unnecessary to have arrays or even function calls. Once I remove the AddOnScreenDebugMessage functions from any of the constructors, the problem goes away. If you like I can provide the exact source code, but it is just as the other comment shows and describes. I would be very interested to know if you can put a debug message in in the constructor, so I can tell if it’s actually something else causing UE 4 Editor to fail.

Now that I realize this, I realize that it’s why the ShooterGame would corrupt projects too. I had always included debug messages where I had added code.

Hey eagletree-

If the call to GEnine is being made before the renderer is created then that can cause problems when the CDO is created when the project is opened. This would coincide with what you said about making the call to GEngine in the constructor. Let me know if you making the call to LoadInventory() and GEngine->AddOnScreenDebugMessage() on BeginPlay() rather than inside the constructor still causes the corruption issue. Additionally, you may want to add an if(GEngine) check to make sure that GEngine is not null.

Cheers

Doug Wilson

Yes, if the call is done from BeginPlay, it works fine. The project does not corrupt then.

I see that this is an answer to the issue, and I voted it up as answered now, but I was hoping someone at Epic would look at making the editor more resilient. I think the biggest issue here is that everything works fine when you save and close, giving a false sense of security that all is well, but then that project can’t be reopened, and without a lot of head scratching, would be considered lost. Thanks for specifically responding to my issue.

Because certain parts of the engine have to be created/loaded for calls to the engine to be successful it would be best to test that it exists before using it. Adding if(GEngine) prior to the GEngine call would only call that code if GEngine has already been created.

If we added a message to UBT to warn when GEngine is used the warning would pop up every time a call to GEngine is made which would also be frustrating.

I understand, but my thought is that there must be some way to keep from aborting the project load, and instead flagging the error. As it is, there is no logical or documented way to get the project back once you have made this mistake.

I will test if having the if(GEngine) would make a difference in whether the project would reload or not, I can’t imagine it would unless a project object code were somehow executed during the load, and that would not make sense to me if it did that sort of thing. It may be my own misunderstanding about what has to occur during the project load, but anything that aborts a load and renders the project unchangeable, would seem to be something that should be avoided by the editor.

I’m not laboring this further! I know how to not have this one happen in the future. I’m just speculating about what would help a noob such as me not spend weeks trying to figure out something like this.