[Python] Pygame: Windows fatal exception: access violation when calling set_mode

Discussão em 'Python' iniciado por Stack, Março 16, 2025.

  1. Stack

    Stack Membro Participativo

    My pygame project has been randomly crashing for a while, but after implementing a way to change the resolution of my screen, the frequency of crashes has dramatically increased. I used to get no errors, just a negative exit code, but after adding faulthandler.enable() into my code, I have been the access violation message mentioned.

    These crashes have always been linked in some way to re-defining the mode of the screen, whether it be changing flags, or the screen resolution. I am always using pygame.SCALED, but also toggle on and off pygame.NOFRAME and pygame.FULLSCREEN. I also use a second surface which i scale down in order to allow other resolutions. See the below code:

    def gameloop() -> None:
    """Starts the while loop that updates the game every iteration."""
    global _running
    if statemanager.state_dict is None:
    msg = "Control module has not been initialised with state_dict."
    raise RuntimeError(msg)

    while _running:
    events.process(pygame.event.get())
    events.eventbinder.notify()
    if system_data.quit:
    logger.info("Quit set to True, saving and exiting game.")
    settings.save()
    _running = False

    statemanager.current_state().update()
    if overlay := overlaymanager.current_overlay(accept_no_overlay=True):
    overlay.update()
    statemanager.current_state().render()
    if overlay:
    overlay.render()

    system_data.dt = pygame.time.Clock().tick(165) / 1000.0
    system_data.window.blit(
    pygame.transform.scale_by(
    system_data.abs_window, system_data.scale_factor
    ),
    (0, 0),
    )
    pygame.display.flip()


    The crashes often are non-reproducible: e.g. I will start my game, change the resolution, game will crash. Start the game again, and it doesn't crash (but crashes later at a random point, however I am pretty sure it won't just crash randomly, its always when I do some event e.g. click with my mouse even if I'm just clicking a random portion of the screen with nothing on it.).
    But the one thing to note, is that however long I stay doing arbitrary things in my program, if I don't mess with the flags/resolution, the game won't ever crash randomly (although sometimes only changing one flag will also never crash - as I said the more changes to the screen mode the more likely the game crashes).

    Sometimes, the crash causes the windows not responding popup. Sometimes it just closes. Sometimes there is not even a access violation message. Sometimes there is a trace to my flag toggling and resolution changing function:

    def toggle_flag(flag: int) -> None:
    """Toggles the given flag and resets the screen mode with the new flags.

    :param flag: The integer value of the flag to toggle.
    """
    system_data.flags ^= flag
    settings.flags[flag_name := DISPLAY_FLAG_NAMES_MAP[flag]] = (
    toggled := not settings.flags[DISPLAY_FLAG_NAMES_MAP[flag]]
    )
    logger.debug(
    "Attempting to toggle flag, and setmode with %s and flags %s %s",
    settings.resolution,
    system_data.flags,
    settings.flags,
    )
    pygame.display.set_mode(settings.resolution, system_data.flags)
    system_data.window = pygame.display.get_surface()
    logger.info(
    "Window flag %s toggled %s", flag_name, "on" if toggled else "off"
    )


    def set_resolution(size: tuple[int, int]) -> None:
    if size == settings.resolution:
    logging.info(
    "Window resolution: %s equal to new resolution. Ignoring call.",
    settings.resolution,
    )
    return
    logger.debug(
    "Attempting to set the mode of the screen with resolution %s and flags"
    " %s %s",
    size,
    system_data.flags,
    settings.flags,
    )
    pygame.display.set_mode(size, system_data.flags)
    logger.info(
    "Window resolution changed from %s to %s.", settings.resolution, size
    )
    settings.resolution = size
    system_data.window = pygame.display.get_surface()
    system_data.window_rect = system_data.window.get_rect()
    update_scale_factor()


    def toggle_fullscreen() -> None:
    """Toggles the fullscreen flag of the screen.

    While this could be done using exclusively the toggle_flag procedure,
    pygame has an inbuilt toggle_fullscreen procedure that is more efficient,
    however doesn't work if already in fullscreen. This procedure abstracts the
    logic for choosing the correct method.

    Also sets the absolute position of the mouse cursor to the same location it
    was before toggling using pynput, since pygame cannot get or set
    coordinates beyond the main window.
    """
    if settings.keep_mouse_pos:
    pygame.mouse.set_visible(False)
    coords = events.get_abs_mouse_pos()
    if system_data.flags & pygame.FULLSCREEN:
    # Using the pygame inbuilt display.toggle_fullscreen to exit fullscreen
    # causes the noframe flag and potentially other flags to disappear.
    # Toggling the flag and manually setting the mode of the screen makes
    # sure all flags are preserved.
    toggle_flag(pygame.FULLSCREEN)
    else:
    system_data.flags ^= pygame.FULLSCREEN
    settings.flags["fullscreen"] = True
    pygame.display.toggle_fullscreen()
    system_data.window = pygame.display.get_surface()
    logger.info(
    "Fullscreen safely toggled on using"
    " pygame.display.toggle_fullscreen()."
    )
    if settings.keep_mouse_pos:
    logger.debug(
    "keep_mouse_pos is True, so setting coords to absolute position: "
    "%s",
    coords,
    )
    events.set_abs_mouse_pos(coords)
    pygame.mouse.set_visible(True)


    def update_scale_factor() -> None:
    if settings.non_int_scaling:
    system_data.scale_factor = min(
    system_data.window_rect.width / system_data.abs_window_rect.width,
    system_data.window_rect.height
    / system_data.abs_window_rect.height,
    )
    else:
    system_data.scale_factor = min(
    system_data.window_rect.width // system_data.abs_window_rect.width,
    system_data.window_rect.height
    // system_data.abs_window_rect.height,
    )
    logger.info(
    "Scale factor calculated as %s, based on the window size: %s and "
    "internal surface size: %s.",
    system_data.scale_factor,
    system_data.window_rect.size,
    system_data.abs_window_rect.size,
    )


    I have implemented some level of logging, but none of the logs suggest anything has gone wrong. Here are some logs from a crash that happened when I changed the resolution of the screen:

    16/03/2025 09:22:03 src.components.events:DEBUG - Mouse button down event detected. Button 1.
    16/03/2025 09:22:03 src.components.audio:INFO - Playing new audio click in audio object Audio(channel_name=sfx). Looping 0 times.
    16/03/2025 09:22:03 src.core.utils:DEBUG - Attempting to set the mode of the screen with resolution (1920, 1080) and flags -2147483104 {'fullscreen': True, 'noframe': True}
    16/03/2025 09:22:03 src.core.utils:INFO - Window resolution changed from (1080, 720) to (1920, 1080).
    16/03/2025 09:22:03 src.core.utils:INFO - Scale factor calculated as 1.0, based on the window size: (1920, 1080) and internal surface size: (1920, 1080).
    16/03/2025 09:22:03 root:INFO - Selected new choice %s, closing popup, calling action if not None and setting text of dropdown head to new choice.
    16/03/2025 09:22:04 src.components.events:DEBUG - Mouse button up event detected. Button 1.
    Windows fatal exception: access violation

    Current thread 0x00004c94 (most recent call first):
    File "C:\Users\r5ne\PycharmProjects\shmup\src\core\main.py", line 67 in gameloop
    File "C:\Users\r5ne\PycharmProjects\shmup\__main__.py", line 8 in <module>
    File "<frozen runpy>", line 88 in _run_code
    File "<frozen runpy>", line 198 in _run_module_as_main
    Windows fatal exception: access violation

    Current thread 0x00004c94 (most recent call first):
    File "C:\Users\r5ne\PycharmProjects\shmup\src\core\main.py", line 67 in gameloop
    File "C:\Users\r5ne\PycharmProjects\shmup\__main__.py", line 8 in <module>
    File "<frozen runpy>", line 88 in _run_code
    File "<frozen runpy>", line 198 in _run_module_as_main

    Process finished with exit code -1073741819 (0xC0000005)


    The traceback just pointed to pygame.display.flip() which doesn't help.
    Some of the events that caused this crash to happen are (but not limited to):

    • Changing the screen resolution or changing the screen flags (happens after an arbitrary amount of resolution changes/flag toggles, but usually more changes = higher chance game crashes).
    • Doing the above without the game crashing and then going about clicking on the screen and interacting with my game (e.g. like the above error log - the last thing i did was click on a button (that didn't do anything related to resetting the screen mode)

    Here is another error, this time caused by toggling the NOFRAME tag on:

    16/03/2025 09:55:52 src.core:INFO - Attempting to load existing config.json file with data: {'flags': {'fullscreen': True, 'noframe': True}, 'resolution': [1920, 1080], 'non_int_scaling': True, 'keep_mouse_pos': True}.
    --some more logs--
    16/03/2025 09:56:04 src.components.events:DEBUG - Mouse button up event detected. Button 1.
    16/03/2025 09:56:04 src.components.events:DEBUG - Mouse button down event detected. Button 1.
    16/03/2025 09:56:04 src.components.audio:INFO - Playing new audio click in audio object Audio(channel_name=sfx). Looping 0 times.
    16/03/2025 09:56:04 src.core.utils:DEBUG - Attempting to toggle flag, and setmode with (1080, 720) and flags 544 {'fullscreen': False, 'noframe': True}
    16/03/2025 09:56:04 src.core.utils:INFO - Window flag noframe toggled on
    16/03/2025 09:56:04 src.components.events:DEBUG - Mouse button up event detected. Button 1.
    Windows fatal exception: access violation
    --blah---
    Process finished with exit code -1073741819 (0xC0000005)


    You can view the full repo or download the project on GitHub here. The bugs are still there and you can test it out by toggling the buttons found in the graphics options menu.

    The most relevant parts of the code should be under the src/core directory.

    Any help on identifying the cause of these bugs would be greatly appreciated.

    Continue reading...

Compartilhe esta Página