Solution for Angband crash on startup when compiled with Visual Studio

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Gordon
    Scout
    • Jan 2010
    • 31

    Solution for Angband crash on startup when compiled with Visual Studio

    Symptoms:

    Birth screens work fine, but Angband crashes with an access violation code 0xc0000005 in ntdll.dll just after displaying "Please wait..." in ui_leave_init().

    Problem:

    Shortly after calling ui_enter_world(), Term_xtra(TERM_XTRA_REACT, 0) is called which then calls init_graphics() in main-win.c This calls ReadDIB2_PNG() in readpng.c to read in the graphic tiles. The crash occurs when png_read_info(png_ptr, info_ptr) is called at line 102.

    Solution:

    libpng12.dll is multi-threaded and so requires Angband to be compiled with support for multi-threaded dlls. To do this you must set Use run-time library to Multithreaded DLL under Code Generation on the C/C++ tab in Project Settings. This causes the /MD flag to be set in the project Makefile.

    Testing Environment:

    Angband Version: 4.05
    OS Version: Windows XP SP3
    Visual Studio Version: 6.0 SP6

    This very important detail should be added to angband_visual_studio_step_by_step.txt.
  • Gordon
    Scout
    • Jan 2010
    • 31

    #2
    Well, it seems that this doesn't work with Visual Studio 2008. I found an alternate solution that seems to work in both Visual Studio 6.0 and Visual Studio 2008. This requires modification of readpng.c. At the beginning of the file, we need to add a function that forces libpng to use our runtime version of fread() instead of the one it was compiled with:

    Code:
    /** 
     * Forces libpng to use the version of fread() from the run time library 
     * that this program was compiled with.
     */
    void ReadFileFunc(png_structp png_ptr, png_bytep data, png_size_t length) {
    	FILE *file = (FILE *)png_get_io_ptr(png_ptr);
    	fread(data, sizeof(png_byte), length, file);
    }
    
    /**
     * Imports a DIB from a PNG file. Once
     * the DIB is loaded, the function also creates a bitmap
     * and palette out of the DIB for a device-dependent form.
     *
     * Returns TRUE if the DIB is loaded and the bitmap/palette created, in which
     * case, the DIBINIT structure pointed to by pInfo is filled with the
     * appropriate handles, and FALSE if something went wrong.
     */
    BOOL ReadDIB2_PNG(HWND hWnd, LPSTR lpFileName, DIBINIT *pInfo, DIBINIT *pMask, BOOL premultiply) {
    Then in the body of ReadDIB2(), replace these lines:

    Code:
    	/* setup error handling for init */
    	png_init_io(png_ptr, fp);
    	png_set_sig_bytes(png_ptr, 8);
    	
    	png_read_info(png_ptr, info_ptr);
    With these:

    Code:
    	/* setup error handling for init */
    	png_set_read_fn(png_ptr, fp, ReadFileFunc);	
    	png_set_sig_bytes(png_ptr, 8);
    	
    	png_read_info(png_ptr, info_ptr);
    Testing Environment:

    Angband Version: 4.0.5
    OS Version: Windows XP SP3, Windows 7 SP1 64 bit
    Visual Studio Version: 6.0 SP6, 2008 SP1

    Comment

    • eastwind
      Apprentice
      • Dec 2019
      • 79

      #3
      still a bug, fix still good

      I've been working to get a build with VS 2019. I hit this bug after character rolling, just as described. My project was using /MDd for the debug configuration (same as /MD except with debug crt library), so I applied the code fix in the second post and it fixed the bug.

      So I can verify that
      1) the bug is still there,
      2) /MD still doesn't fix it
      3) the code fix does still fix it.

      Thanks for the fix Gordon!

      Comment

      • Nick
        Vanilla maintainer
        • Apr 2007
        • 9647

        #4
        Thanks, I've filed this and your other recent fix as bugs to be fixed (well, I've filed bugs, which the aforementioned are the fixes for).
        One for the Dark Lord on his dark throne
        In the Land of Mordor where the Shadows lie.

        Comment

        • eastwind
          Apprentice
          • Dec 2019
          • 79

          #5
          I've created a github account and made a local clone (as opposed to just downloading the src zip), so I'm getting closer to being able to submit bugs and fixes myself.

          Comment

          • eastwind
            Apprentice
            • Dec 2019
            • 79

            #6
            screenshot crashes

            Something is still not right in png-land for windows (VS compiler). Running with the above fix applied, I tried to take a screenshot, and Angband exited with code 3. No popup, no exceptions. I debugged it, and png_write_image or something it calls within the same dll is calling abort().

            It's dying in this code from SaveWindow_PNG:

            Code:
            		SelectObject(hDC, hbmOld);
            		DeleteObject(hbmScreen);
            		DeleteDC(hDC);
            	}  
            
            	/* Write the file */
            	if (noerror) {
            		png_write_image(png_ptr, row_pointers);  /* <=== dies here */
            		png_write_end(png_ptr, NULL);
            	}
            
            	/* Release the image memory */
            	for (y = 0; y < height; ++y)
            		free(row_pointers[y]);
            	free(row_pointers);
            I don't have symbols for libpng12.dll, but I haven't tried real hard to find them. I stepped through the assembly for a while, just to exercise old fading skills. It's getting into the function, doing some stuff, and gets to a loop that is supposed to iterate 692 times - and 692 is the 'height' from screenshot.c. It iterates that loop about 420 times before calling abort() from a libpng subroutine called out of that 'screen height' loop.

            With the particular save game, and with the exact same term window setup, it was repeatable at that same 420 iterations point.

            Then I gave up and went to bed.

            The obvious workaround is don't take screenshots using the in-game function, just use the windows screenshot function.

            Comment

            Working...
            😀
            😂
            🥰
            😘
            🤢
            😎
            😞
            😡
            👍
            👎