Day 43: Live coding crashing

Hello friends.

I´m geting a crashing and this message from VS whenever I compile the code and the game is still running.

Unhandled exception at 0x0000000000000000 in Win32_main_handmadehero.exe: 0xC0000005: Access violation executing location 0x0000000000000000.

While the compiler terminal shows this

handmadehero.cpp
Creating library handmadehero.lib and object handmadehero.exp
Win32_main_handmadehero.cpp
LINK : fatal error LNK1104: cannot open file 'Win32_main_handmadehero.exe'

I think it was working fine until the day before.
My system is VS 2013 and Win7.

UPDATE.

I rollback a few days.
The problem was the build.bat change in day 39, with the lock.tmp file.
I´m looking into it.

UPDATE 2.
Yes, the problem was with the lock file.

Edited by ThadeuMelo on Reason: New cause for crash found
When VS shows error then check out debugger to understand what is wrong.
What line code stopped?
What are values of variables this line accesses?
What is the call stack?

Failing to link main exe file (Win32_main_handmadehero.exe) is expected. Live coding is supposed to reload only game code (dll file), not main executable.

Edited by Mārtiņš Možeiko on
It crashes right at the call for UpdateandRender.

Game.UpdateAndRender(&Thread, &GameMemory, NewInput, &Buffer);

Thread = {Placeholder=0 }
GameMemory = {IsInitialized=1 PermanentStorageSize=67108864 PermanentStorage=0x0000020000000000 TransientStorageSize = 104857600 ...}

NewInput = 0x000000000012ed40 {MouseButtons=0x000000000012ed40 {{HalfTransitionCount=110 EndedDown=0 }, {HalfTransitionCount=...}, ...} ...}

Buffer = {Memory=0x00000000021c0000 Width=960 Height=540 Pitch=3840 BytesPerPixel =4}
Yep, the problem is with the lock file.
1
GetFileAttributesEx(...)
fails to find "lock.tmp" when I run build with the game is running and I rebuid the code.

I put these lines in the build bat

1
2
3
4
5
6
7
del lock.tmp
echo WAITING FOR PDB > lock.tmp
echo WAITING FOR PDB > lock_%random%.tmp
del lock.tmp
echo WAITING FOR PDB > lock.tmp
del lock.tmp
echo WAITING FOR PDB > lock.tmp


And the prompt shows that lock.tmp files are created every time...

What a mistery.


Edited by ThadeuMelo on
What do you mean by "lock files are created every time"? If you do "echo >file" then that is supposed to create new "file" every time.

When GetFileAttributeEx fails, check the last windows error. You can do that by calling GetLastError() or, putting breakpoint in if(!Result.IsValid) branch and examining @err pseudo-variable (put it in watch window, debugger will show last windows error).
I meant that echo "WAIT > lock.tmp" is working and there is supose to be a lock.tmp file.

I also did

1
2
3
4
5
6
7
8
if(!GetFileAttributesEx(LockFileName, GetFileExInfoStandard, &Ignored)){
.
.
.
}
else{
OutputDebugStringA("LOCK FILE MISSING!!!");
}


And it output the error only when compiling with the code running. Even though the path to the file is correct.

¯\_(ツ)_/¯
So what is windows error, GetLastError() value or @err in debugger?
Following this exemple FormatMessage function I´m getting 0 as error code with GetLastError() in the else case of Win32LoadGameCode.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
    if(!GetFileAttributesEx(LockFileName, GetFileExInfoStandard, &Ignored))
    {
           .
           .
           .
    }
	else{
		

	
		OutputDebugStringA("LOCK FILE NOT FOUND!!!\n");
		    if(!GetProcessId(NULL))
				ErrorExit(TEXT("GetProcessId"));
	}


If you are calling GetLastError inside ErrorExit function, then this won't work. Because GetProcessId resets last error. You need to call GetLastError directly after function which generates error. It should be first win32 API call in else block.

Just put "DWORD e = GetLastError();" there and examine :e" value in debugger.

Edited by Mārtiņš Možeiko on
1
2
3
	Game.UpdateAndRender(&Thread, &GameMemory, NewInput, &Buffer);
							
	DWORD e = GetLastError();


e = 0 when it crashes.

Edited by ThadeuMelo on
You misunderstood me. Crash happens because UpdateAndRender pointer is NULL. This pointer is set to NULL in Win32LoadGameCode function:
1
2
3
4
5
    if(!Result.IsValid)
    {
        Result.UpdateAndRender = 0;
        Result.GetSoundSamples = 0;
    }

So put GetLastError() in this if statement. Most likely LoadLibraryA fails or GetProcAddress fails.

Edited by Mārtiņš Možeiko on
e1 and e are always zero

1
2
3
4
5
6
7
8
9
	
DWORD e1 = GetLastError();
	DWORD e;
    if(!Result.IsValid)
    {
        Result.UpdateAndRender = 0;
        Result.GetSoundSamples = 0;
		e = GetLastError();
    }


LoadLibraryA() is inside the "if" that fails when checking for lock file.

UPDATE: SOLUTION?

Well, it´s all a mather of time. When I put a breakpoint right at GetFileAttributesEx(...) it works fine every time.
But if the code is running without a BP ... it crashes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
if exist lock.tmp (
    echo file exists
) else (
    echo file doesn't exist
)
del lock.tmp
ping 127.0.0.1 -n 5 > nul
if exist lock.tmp (
    echo FILE EXISTS
) else (
    echo FILE DOSEN'T EXISTS
)


I tried to put some delays in the build file, but for no avail. The prompt shows the file does not exists correctly, but the code then belives it exists.

UPDATE 2: SOLUTION!!

Inside the main loop the first time after a Live compile it shows that the lock file exists

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
while (GlobalRunning)
{
	FILETIME LockFileTime = Win32GetLastWriteTime(GameCodeLockFullPath);
	if (CompareFileTime(&OldLockFileTime , &LockFileTime)){
	OutputDebugStringA("LOCK FILE TIME IS NOT THE SAME\n");
        Sleep(1000);
        }
        .
        .
        .

}


So, finaly, add a 1 sec sleep when I the lock file still exists fix the problem. I also PDBs files are working fine with break points after reload.

Well ,only 259 days to catch you guys. Thank you.

Edited by ThadeuMelo on